Flask OIDC with Keycloak returning None when trying to get 'openid_id' and 'role' fields

1.1k views Asked by At

I'm trying to build some test applications using Flask-ODBC + Keycloak.

I successfully started Keycloak, created a Realm, a role and an user to who this role is assigned. Now I'm trying to get the 'role' and 'openid_id' fields from the OpenIDConnect object but these two fields are returning None.

My application code is the following

import json

import flask
from flask import Flask, render_template, g
import flask_login
from flask_login import login_required
from flask_oidc import OpenIDConnect

from model.user import User

app = Flask(__name__)

login_manager = flask_login.LoginManager()
login_manager.init_app(app)

# Our mock database.
users = {'[email protected]': {'pw': 'secret'}}

app.config.update({
    'SECRET_KEY': 'u\x91\xcf\xfa\x0c\xb9\x95\xe3t\xba2K\x7f\xfd\xca\xa3\x9f\x90\x88\xb8\xee\xa4\xd6\xe4',
    'TESTING': True,
    'DEBUG': True,
    'OIDC_CLIENT_SECRETS': 'client_secrets.json',
    'OIDC_ID_TOKEN_COOKIE_SECURE': False,
    'OIDC_REQUIRE_VERIFIED_EMAIL': False,
    'OIDC_VALID_ISSUERS': ['http://localhost:8080/auth/realms/MyDemo'],
    'OIDC_OPENID_REALM': 'http://localhost:5000/oidc_callback'
})
oidc = OpenIDConnect(app)


@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('email')
    else:
        return 'Welcome anonymous, <a href="/private">Log in</a>'


@app.route('/private')
@oidc.require_login
def hello_me():
    info = oidc.user_getinfo(['email', 'openid_id', 'role'])
    print(info)
    return ('Hello, %s (%s)! <a href="/">Return</a>' %
            (info.get('email'), info.get('openid_id')))


@app.route('/api')
@oidc.accept_token(True, ['openid'])
def hello_api():
    return json.dumps({'hello': 'Welcome %s' % g.oidc_token_info['sub']})


@app.route('/logout')
def logout():
    oidc.logout()
    return 'Hi, you have been logged out! <a href="/">Return</a>'


if __name__ == '__main__':
    app.run('localhost', port=5000)

Inside hello_me() I try to get the 'openid_id' and 'role' and print it. The problem is I'm getting None in these fields. I can get the email correctly.

Can you help me with finding out what mistakes I'm making?

1

There are 1 answers

2
Jan Garaj On BEST ANSWER

https://flask-oidc.readthedocs.io/en/latest/

user_getinfo(fields, access_token=None)

Returns: The values of the current user for the fields requested. The keys are the field names, values are the values of the fields as indicated by the OpenID Provider. Note that fields that were not provided by the Provider are absent.

Your provider (Keycloak) doesn't expose openid_id details in the token apparently, so field is absent. Very likely you didn't configure OIDC client in the Keycloak correctly. Make sure you have added correct mappers/scopes to used OIDC client in the Keycloak, which expose requested details into openid_id claim.