Mercurial > prosody-modules
diff mod_http_oauth2/mod_http_oauth2.lua @ 5337:8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Actually filling in those details is left to another module because I
don't really wanna mix in a dependency on PEP or mod_vcard here, those
implementation details can be in a second module. Some might want to
fill this from LDAP or something as well.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Mon, 10 Apr 2023 10:49:02 +0200 |
parents | 77ac04bd2f65 |
children | cd195283127f |
line wrap: on
line diff
--- a/mod_http_oauth2/mod_http_oauth2.lua Mon Apr 10 10:47:51 2023 +0200 +++ b/mod_http_oauth2/mod_http_oauth2.lua Mon Apr 10 10:49:02 2023 +0200 @@ -81,13 +81,15 @@ return array(scope_string:gmatch("%S+")); end +local openid_claims = set.new({ "profile"; "email"; "address"; "phone" }); + local function filter_scopes(username, requested_scope_string) local selected_role, granted_scopes = nil, array(); if requested_scope_string then -- Specific role(s) requested local requested_scopes = parse_scopes(requested_scope_string); for _, scope in ipairs(requested_scopes) do - if scope == "openid" then + if scope == "openid" or openid_claims:contains(scope) then granted_scopes:push(scope); end if selected_role == nil and usermanager.user_can_assume_role(username, module.host, scope) then @@ -758,16 +760,35 @@ module:log("debug", "UserInfo query failed token validation: %s", err) 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 scopes = set.new() + if type(token_info.grant.data) == "table" and type(token_info.grant.data.oauth2_scopes) == "string" then + scopes:add_list(parse_scopes(token_info.grant.data.oauth2_scopes)); + else + module:log("debug", "token_info = %q", token_info) + end + + if not scopes:contains("openid") then + module:log("debug", "Missing the 'openid' scope in %q", scopes) + -- The 'openid' scope is required for access to this endpoint. + return 403; + end 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. } + + local token_claims = set.intersection(openid_claims, scopes); + if not token_claims:empty() then + -- Another module can do that + module:fire_event("token/userinfo", { + token = token_info; + claims = token_claims; + username = jid.split(token_info.jid); + userinfo = user_info; + }); + end + return { status_code = 200; headers = { content_type = "application/json" };