6

I'm trying to use Flask-oidc in a simple flask application in order to add authentication via keycloak.

However, once I log-in with valid credentials it goes back to /oidc_callback which doesn't exist.

The flask logs show a lot of attempts of redirect with 302 result code:

127.0.0.1 - - [26/Nov/2018 10:56:54] "GET /oidc_callback?state=eyJjc3JmX3Rva2VuIjogIlluRDc0UUVLVGhRRkw5TGtuRU9RZGprNTBheVk1cERkIiwgImRlc3RpbmF0aW9uIjogImV5SmhiR2NpT2lKSVV6STFOaUo5LkltaDBkSEE2THk5c2IyTmhiR2h2YzNRNk5UQXdNUzlzYjJkcGJpSS50MVVCRUszbFBxSmZRSzkzMHB5UktBNUZibmNtU0h6TElLblgweXgtTElJIn0%3D&session_state=96eb0bd8-a4a3-49a5-a00c-f4d621cd68e0&code=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..T5U8hwYX2ot7Llzo39-cyw.4r-lLPZ1So1j4jPqfVwW5zKgtFjMR_f38ls71SwyqrwLVnE-OfZIi0O74pgzNLQEhxFu2nT-o-7_iNuqv5EIHuaIk_mp-xAY7TlaCViM9NvEDvs78iTTmLwPHsDI20SWuPS08K1wING9CXjhZLudLsBAoWRomFHGfDI_Xyd90lb0wWa73vgcMoeatlt1sEbJTo7XxuDBg-JvyzGfqclvuh5bk848q-07tkDsTKETIK-0wLxb-vUaoqkYmqRVQ3-p.PP0YzjGpjvIqCTNCk3IZTQ HTTP/1.1" 302 -
127.0.0.1 - - [26/Nov/2018 10:56:54] "GET /login HTTP/1.1" 302 -
127.0.0.1 - - [26/Nov/2018 10:56:54] "GET /oidc_callback?state=eyJjc3JmX3Rva2VuIjogIlluRDc0UUVLVGhRRkw5TGtuRU9RZGprNTBheVk1cERkIiwgImRlc3RpbmF0aW9uIjogImV5SmhiR2NpT2lKSVV6STFOaUo5LkltaDBkSEE2THk5c2IyTmhiR2h2YzNRNk5UQXdNUzlzYjJkcGJpSS50MVVCRUszbFBxSmZRSzkzMHB5UktBNUZibmNtU0h6TElLblgweXgtTElJIn0%3D&session_state=96eb0bd8-a4a3-49a5-a00c-f4d621cd68e0&code=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..JpVESxYMF7ApS07y_cOxmA.FRX0kTvi_YvRTYnA8OVmkuEHDrVr8cf9Xa9zk2KfXovb4f9vpz6oIcuqjM-EYVfC5PVLYObhVQWW9HZW4Omcewpp-t9M2z7YRZqMAuyeYAsN7_uctScoh6Q634YDSlXiyXnQ81zg3VwVC_C3pWjVnlm8ZLKb5mRAnMDe4li3FXj9OYWlzJu3Ti18TOw2ig2eB0H0D-jdMcMS4Y8CtLOX_IEKQs6f6IXgl6jpo7uDYvKnwQ11zVaX-Bvw8oan79M2.ZwuIdSCc4QYv2imcbp2Tig HTTP/1.1" 302 -
127.0.0.1 - - [26/Nov/2018 10:56:54] "GET /login HTTP/1.1" 302 -
127.0.0.1 - - [26/Nov/2018 10:56:54] "GET /oidc_callback?state=eyJjc3JmX3Rva2VuIjogIlluRDc0UUVLVGhRRkw5TGtuRU9RZGprNTBheVk1cERkIiwgImRlc3RpbmF0aW9uIjogImV5SmhiR2NpT2lKSVV6STFOaUo5LkltaDBkSEE2THk5c2IyTmhiR2h2YzNRNk5UQXdNUzlzYjJkcGJpSS50MVVCRUszbFBxSmZRSzkzMHB5UktBNUZibmNtU0h6TElLblgweXgtTElJIn0%3D&session_state=96eb0bd8-a4a3-49a5-a00c-f4d621cd68e0&code=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..4SU_gWqEUykjTc78z47zYg.TzPRPlLCmJ7Ofzp5wHMwJam4pmc21_qo0p8bIpULbDE8Q39IESxSO2Sxqvxi67xnNXL90CqbG5uRt3k_2oDPzFUCjoNw0EDibiqSPlnuMNgizGSCXAyVV8DafMJqTGhnbHUUpGVqLzMosIlfwM14jhjXFick0GaC10TPFFdiGZdfVFZlSH95XtrGQ-e9dfgpvi5ioPhlQ1S9Eo9kqSh9WwhOCfGRZe9GNLNFtUT9YCPHHmLirRNLc5NiOdm-kH3L.2Mmopk3YJ0_AiCjk2ArKwQ HTTP/1.1" 302 -
...

And after a while of trying I get also this error in the console:

oauth2client.client.FlowExchangeError
oauth2client.client.FlowExchangeError: invalid_grantCode not valid

This is my flask app code:

import json
from flask import Flask, g
from flask_oidc import OpenIDConnect

app = Flask(__name__)

app.config.from_mapping(
        SECRET_KEY='b3d6a4b1-7f8d-4499-a1ae-6faa053d5b67',
        OIDC_CLIENT_SECRETS='./keycloak.json',
        OIDC_VALID_ISSUERS=['http://localhost:8090/auth/realms/myrealm'],
        OIDC_INTROSPECTION_AUTH_METHOD='client_secret_post',
        OIDC_TOKEN_TYPE_HINT='access_token',
    )

oidc = OpenIDConnect(app)


@app.route("/")
def hello():
    if oidc.user_loggedin:
        return 'Welcome %s' % oidc.user_getfield('email')
    else:
        return 'Not logged in'


@app.route('/login')
@oidc.require_login
def login():
    return 'Welcome %s' % oidc.user_getfield('email')


@app.route('/api')
@oidc.accept_token(require_token=True)
def my_api():
    return json.dumps('Welcome %s' % g.oidc_token_info['sub'])

This is my keycloak.json:

{
  "web":
   {
     "client_id": "MyClient",
     "client_secret": "b3d6a4b1-7f8d-4499-a1ae-6faa053d5b67",
     "auth_uri": "http://localhost:8090/auth/realms/myrealm/protocol/openid-connect/auth",
     "token_uri": "http://localhost:8090/auth/realms/myrealm/protocol/openid-connect/token",
     "token_introspection_uri": "http://localhost:8090/auth/realms/myrealm/protocol/openid-connect/token/introspect",
     "realm": "myrealm",
     "ssl-required": "none",
     "resource": "MyClient"
   }
}

In my Keycloak admin console I have set-up my client and as far as I understand, the fact that it shows the keycloak login screen properly is because it's configured as expected, however I cannot make work the app once the login is performed.

enter image description here

I also tried to override the default callback (which I'm not clear about if I have to implement it or not btw):

For that I added this (taken from the docs):

OVERWRITE_REDIRECT_URI='http://localhost:5001/custom_callback'

@app.route('/custom_callback')
@oidc.custom_callback
def callback(data):
    return 'Hello. You submitted %s' % data

And this to my keycloak.json:

     "redirect_uris": [
         "http://localhost:5001/custom_callback"
     ],

But no success in recognizing the logged in user. Though I see a state var in the querystring.. what should I do with that?

What am I missing?

Should I implement a custom callback? in that case can anybody give an example of how to make my flask app aware of the user logged in?

Thanks a lot in advance!

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
magnoz
  • 1,939
  • 5
  • 22
  • 42
  • Do I have to override the callback and manually perform an access token request with the code I get from keycloak in the redirect? if that's the case what's the point of the flask-oidc library? I'd appreciate any help – magnoz Nov 26 '18 at 14:01
  • Were you able to solve this problem? – NIMROD MAINA Apr 16 '19 at 12:48
  • No. And after some time of trying without success we decided to go for a different approach. – magnoz May 01 '19 at 13:32
  • Anybody had any success with this? @magnoz can you share the other approach you have used. – Giridhar Bandi Sep 10 '19 at 14:52
  • I'm using docker and implemented a GW using nginx, and all the routings go through it, meaning that if there is any service that needs to be authenticated or secured, I manage it there, for the main services I use jtw authentication over a python framework. – magnoz Sep 11 '19 at 15:14
  • I can not even get the keyclaok login page! `@oidc.require_login` lands me `{"error":"invalid_request","error_description":"Missing parameter: username"}` @magnoz can you share your keycloak settings, I don't know what am I doing wrong. – Ahmad Karim Apr 29 '21 at 06:54

2 Answers2

1

The problem is the iat check.. This check will allow connection if the issuance time (must be lower that expiry time) is larger that the current time, if not, this check will return false and display error. So to resolve the problem you need to set 'OIDC_CLOCK_SKEW' and create audience scope keycloak side.

Here the part of code :

# step 10: check iat
    if id_token['iat'] < (time.time() -
                          current_app.config['OIDC_CLOCK_SKEW']):
        logger.error('Token issued in the past')
        return False

I don't know if it's the good way or if it's a server/package issue but it works for me. Because it's not possible to have an issuance time >= current_time, right ?

My configuration :

app.config.update({
    'DEBUG': True,
    'TESTING': True,
    'SECRET_KEY': 'testest',
    'OIDC_CLIENT_SECRETS': 'client_secrets.json',
    'OIDC_ID_TOKEN_COOKIE_SECURE': False,
    'OIDC_REQUIRE_VERIFIED_EMAIL': False,
    'OIDC_USER_INFO_ENABLED': True,
    'OIDC_OPENID_REALM': 'fake_realm',
    'OIDC_SCOPES': ['openid', 'email', 'profile'],
    'OIDC_INTROSPECTION_AUTH_METHOD': 'client_secret_post',
    'OIDC_RESOURCE_CHECK_AUD': True, #Audience
    'OIDC_CLOCK_SKEW': 560 #iat must be > time.time() - OIDC_CLOCK_SKEW
}) 

I put that here to help others to resolve it :)

EDIT:

In your case, in addition you also need to add "redirect_uris" to your json like this: (it must be the same uri that keycloak side)

{
    "web": {
        "issuer": "https://{server_name}/auth/realms/fake_realm",
        "auth_uri": "https://{server_name}/auth/realms/fake_realm/protocol/openid-connect/auth",
        "client_id": "fake_realm",
        "client_secret": "ac981e95-f97b-******-*******-*****",
        "redirect_uris": [
            "http://localhost:5000/oidc_callback"
        ],
        "userinfo_uri": "https://{server_name}/auth/realms/fake_realm/protocol/openid-connect/userinfo",
        "token_uri": "https://{server_name}/auth/realms/fake_realm/protocol/openid-connect/token",
        "token_introspection_uri": "https://{server_name}/auth/realms/fake_realm/protocol/openid-connect/token/introspect"
    }
}
Briareos
  • 36
  • 4
0

I had solved this problem by changing time setting. I had set the time correctly and problem is solved.

imxitiz
  • 3,920
  • 3
  • 9
  • 33