Flask-OIDC with keycloak - oidc_callback default callback not working

2024/12/9 20:56:36

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 OpenIDConnectapp = 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!

Answer

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 iatif 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"}
}
https://en.xdnf.cn/q/72842.html

Related Q&A

Matplotlib: reorder subplots

Say that I have a figure fig which contains two subplots as in the example from the documentation:I can obtain the two axes (the left one being ax1 and the right one ax2) by just doing:ax1, ax2 = fig.a…

Filter values in a list using an array with boolean expressions

I have a list of tuples like this:listOfTuples = [(0, 1), (0, 2), (3, 1)]and an array that could look like this:myArray = np.array([-2, 9, 5])Furthermore, I have an array with Boolean expressions which…

Show two correlation coefficients on pairgrid plot with hue (categorical variable) - seaborn python

I found a function to compute a correlation coefficient and then add it to a pair plot (shown below). My issue is that when I run a pairplot with hue (a categorical variable) the correlation coefficien…

How to properly setup vscode with pyside? Missing suggestions

Im very new to pyside, qt and python. I managed to setup a project with a basic window and a push button which closes the app. My problem is, that somehow vscode wont show all properties available, eve…

Split marker and line in Legend - Matplotlib

I want to make a legend where I specify the value for the markers and the value for the lines but not the combination of both.This example should help to illustrate my goal:import matplotlib.pyplot as …

How do I loop over all items in a DynamoDB table using boto?

Id like to query a DynamoDB table and retrieve all the items and loop over them using boto. How do I structure a query or scan that returns everything in the table?

install pyopencv with pip on Mac OS X

I am trying to install pyopencv with pip in OS X Mountain Lion and it fails by import setuptools. Following is my work. what is "Library" in setuptools? I have not seen that before. I alread…

OpenCV remap interpolation error?

Im using opencv remap function to map an image to another coordinate system. However, my initial tests indicate that there are some issues with the interpolation. Here, I give a simple example of a co…

Installing python with python win32 extensions on a network drive

I need to keep a large number of Windows XP machines running the same version of python, with an assortment of modules, one of which is python-win32. I thought about installing python on a network dri…

Python pytest hangs. For instance, pytest --version simply hangs

The following hangs:PS C:\Users\Fowler> pytest --version Notes:I am in Windows 10. By hang, I mean at least 5 minutes of waiting for the pytest --version to return... While waiting for pytest, pyth…