I was able to extend the oidc flask example with this handler
@bp.route("/.well-known/openid-configuration")
def well_known_openid_configuration():
def external_url(function_name):
return url_for(function_name, _external=True)
return jsonify({
"authorization_endpoint": external_url('.authorize_endpoint'),
"token_endpoint": external_url('.token_endpoint'),
"userinfo_endpoint": external_url('.userinfo_endpoint'),
"jwks_uri": external_url('.jwks_endpoint'),
# Do I even need this one?
# IMO the OIDC server doesn't have a concept of a user being still logged in? --mh
# "end_session_endpoint": "http://oidc:4000/openid/end-session",
"id_token_signing_alg_values_supported": [
"HS256",
"RS256"
],
"issuer": JWT_CONFIG['iss'],
"response_types_supported": [
"code",
# TODO check what it takes to support these too
# "id_token",
# "id_token token",
# "code token",
# "code id_token",
# "code id_token token"
],
"subject_types_supported": [
"public"
],
"token_endpoint_auth_methods_supported": [
# TODO is supporting both a good idea? --mh
"client_secret_post",
"client_secret_basic"
],
})
Turns out implementing the jwks_uri endpoint wasn't so hard, it works roughly like this:
def load_public_keys():
public_key_path = Path("etc") / "public.pem"
public_key = JsonWebKey.import_key(public_key_path.read_bytes())
public_key["use"] = "sig"
public_key["alg"] = "RS256"
return KeySet([public_key])
@bp.route("/oauth/jwks")
def jwks_endpoint():
return jsonify(load_public_keys().as_dict())
To get authlib to use the private key and set the key id (kid), this was required in the JWT_CONFIG
JWT_CONFIG = {
"key": "secret-key",
"alg": "RS256",
"iss": "https://sntl-publishing.com",
"exp": 3600,
}
private_key_path = Path('etc') / 'private.pem'
private_key = JsonWebKey.import_key(private_key_path.read_text())
JWT_CONFIG['key'] = KeySet([private_key]).as_dict()
It seems to be fixed in the master version in the repo, but in the currently released version you need the as_dict() call on the KeySet - else the kid is not part of the generated id token nd the client will not be able to verify it with the information from the jwks_uri endpoint.