diff mod_http_oauth2/mod_http_oauth2.lua @ 5228:77cd01af06a9

mod_http_oauth2: Implement the OpenID userinfo endpoint Needed for OIDC
author Kim Alvefur <zash@zash.se>
date Thu, 09 Mar 2023 14:46:06 +0100
parents 3439eb37f23b
children c24a622a7b85
line wrap: on
line diff
--- 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" };