I'm trying to implement Flask-OIDC
and Keycloak
in a Flask app run inside a Gitpod
workspace.
I'm running the application and the Keycloak
server like this:
./keycloak-11.0.3/bin/standalone.sh -b 0.0.0.0 -bmanagement 0.0.0.0 &
flask run --host=0.0.0.0 &
Based on this post
I'm able to redirect to the Keycloak
login page for regular users from within the Flask
application, but when I login with an existing user I get the following:
oauth2client.client.FlowExchangeError: Invalid response: 301
My client_secrets.json
currently looks something like this:
{
"web": {
"auth_uri": "http://keycloak-hostname-gitpod/auth/realms/realm/protocol/openid-connect/auth",
"issuer": "http://keycloak-hostname-gitpod/auth/realms/realm",
"userinfo_uri": "http://keycloak-hostname-gitpod/auth/realms/realm/protocol/openid-connect/userinfo",
"client_id": "client",
"client_secret": "client_secret",
"redirect_uris": ["http://flask-app-hostname-gitpod/oidc_callback"],
"token_uri": "http://keycloak-hostname-gitpod/auth/realms/realm/protocol/openid-connect/token",
"token_introspection_uri": "http://keycloak-hostname-gitpod/auth/realms/realm/openid-connect/token/introspect"
}
}
Relevant client configuration inside keycloak:
Root URL: http://flask-app-hostname-gitpod/*
Valid Redirect URIs: http://flask-app-hostname-gitpod/*
Admin URL: http://flask-app-hostname-gitpod/*
Web Origins: http://flask-app-hostname-gitpod
I use http
in all of these urls instead of https
, because when I use https
Keycloak
says the redirect_uri
is invalid. This seems to be the actual problem here since the gitpod urls use https
, but I'm not sure how to handle this. I've tried some solutions like described here, but couldn't get them to work.
Relevant part routing:
@app.route("/")
def hello_world():
if oidc.user_loggedin:
return (
'Hello, %s, <a href="/private">See private</a> '
'<a href="/logout">Log out</a>'
) % oidc.user_getfield("preferred_username")
else:
return 'Welcome anonymous, <a href="/private">Log in</a>'
@app.route("/private")
@oidc.require_login
def test():
return "test"
Parts of standalone.xml
that might be relevant:
<http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true" read-timeout="30000" proxy-address-forwarding="true" />
<https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true" read-timeout="30000" />
Update
After following changing the http urls to https as Jan Garaj suggested and setting the OVERWRITE_REDIRECT_URI
I don't get the invalid response: 301
error anymore:
OVERWRITE_REDIRECT_URI = "https://flask-app-hostname-gitpod/oidc_callback"
Now I'm able to go to the keycloak login form, but on logging in I now get:
oauth2client.client.FlowExchangeError: Invalid response: 401.
These are the requests made:
https://keycloak-hostname-gitpod/auth/realms/realm/login-actions/authenticate?session_code=session_code&execution=execution&client_id=client&tab_id=tab_id
https://flask-app-hostname-gitpod/oidc_callback?state=state&session_state=session_state&code=code
After much trial end error I've finally figured out what the problem was.
The redirect problem in the original question was solved by setting OVERWRITE_REDIRECT_URI
:
OVERWRITE_REDIRECT_URI = "https://flask-app-hostname-gitpod/oidc_callback"
The oidc_callback
request was still not working however, I was getting this:
oauth2client.client.FlowExchangeError: Invalid response: 401.
Jan Garaj's comment made me realise the problem was that the token endpoint request was not working.
I had checked the token endpoint uri multiple times and copied the value from:
https://flask-app-hostname-gitpod/auth/realms/demo/.well-known/openid-configuration
but it still didn't work.
The reason it didn't work was actually unrelated to my Keycloak
configuration, but the way my keycloak server was running inside Gitpod
.
Gitpod
set the port that the keycloak server was running on to private
. Because the keycloak server was running on a private port, the request to the follwing url failed:
https://keycloak-hostname-gitpod/auth/realms/demo/protocol/openid-connect/token
After making the port public it worked.
if you already know that you want a particular port exposed, you can configure it in .gitpod.yml:
ports:
- port: 5000
onOpen: open-preview
- port: 8080