# HG changeset patch # User Kim Alvefur # Date 1678369566 -3600 # Node ID 77cd01af06a9fd3e5871105ebdf4280ab3ddaac2 # Parent 0dcd956d7bc53eff74e0407e75adb70e90f5c476 mod_http_oauth2: Implement the OpenID userinfo endpoint Needed for OIDC diff -r 0dcd956d7bc5 -r 77cd01af06a9 mod_http_oauth2/mod_http_oauth2.lua --- a/mod_http_oauth2/mod_http_oauth2.lua Thu Mar 09 13:15:13 2023 +0100 +++ b/mod_http_oauth2/mod_http_oauth2.lua Thu Mar 09 14:46:06 2023 +0100 @@ -617,6 +617,33 @@ handle_register_request = nil end +local function handle_userinfo_request(event) + local request = event.request; + local credentials = get_request_credentials(request); + if not credentials or not credentials.bearer_token then + return 400; + end + local token_info = tokens.get_token_info(credentials.bearer_token); + if not token_info then + return 403; + end + -- TODO check that they actually have access to the userinfo endpoint, aka + -- the 'openid' scope. Tokens currently contain the JID in plain text so + -- we're not really returning anything they did not know already. + + local user_info = { + iss = get_issuer(); + sub = url.build({ scheme = "xmpp"; path = token_info.jid }); + -- Additional UserInfo fields could be pulled from vcard4, depending on + -- permissions and scopes granted. + } + return { + status_code = 201; + headers = { content_type = "application/json" }; + body = json.encode(user_info); + }; +end + module:depends("http"); module:provides("http", { route = { @@ -625,6 +652,7 @@ ["POST /authorize"] = handle_authorization_request; ["POST /revoke"] = handle_revocation_request; ["POST /register"] = handle_register_request; + ["GET /userinfo"] = handle_userinfo_request; -- Optional static content for templates ["GET /style.css"] = templates.css and { @@ -667,6 +695,7 @@ authorization_endpoint = handle_authorization_request and module:http_url() .. "/authorize" or nil; token_endpoint = handle_token_grant and module:http_url() .. "/token" or nil; jwks_uri = nil; -- TODO? + userinfo_endpoint = handle_register_request and module:http_url() .. "/userinfo" or nil; registration_endpoint = handle_register_request and module:http_url() .. "/register" or nil; scopes_supported = usermanager.get_all_roles and array(it.keys(usermanager.get_all_roles(module.host))) or { "prosody:restricted"; "prosody:user"; "prosody:admin"; "prosody:operator" };