Mercurial > prosody-modules
comparison mod_http_oauth2/mod_http_oauth2.lua @ 5502:fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
This lets additional modules define what scopes they might add to the
userinfo endpoint, or other things.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Thu, 01 Jun 2023 18:16:13 +0200 |
parents | 57ce8c4017e7 |
children | ae007be8a6bd |
comparison
equal
deleted
inserted
replaced
5501:57ce8c4017e7 | 5502:fd4d89a5b8db |
---|---|
70 body = _render_html(template, data); | 70 body = _render_html(template, data); |
71 }; | 71 }; |
72 return resp; | 72 return resp; |
73 end | 73 end |
74 | 74 |
75 local authorization_server_metadata = nil; | |
76 | |
75 local tokens = module:depends("tokenauth"); | 77 local tokens = module:depends("tokenauth"); |
76 | 78 |
77 local default_access_ttl = module:get_option_number("oauth2_access_token_ttl", 86400); | 79 local default_access_ttl = module:get_option_number("oauth2_access_token_ttl", 86400); |
78 local default_refresh_ttl = module:get_option_number("oauth2_refresh_token_ttl", nil); | 80 local default_refresh_ttl = module:get_option_number("oauth2_refresh_token_ttl", nil); |
79 | 81 |
103 -- string -> array | 105 -- string -> array |
104 local function parse_scopes(scope_string) | 106 local function parse_scopes(scope_string) |
105 return array(scope_string:gmatch("%S+")); | 107 return array(scope_string:gmatch("%S+")); |
106 end | 108 end |
107 | 109 |
108 local openid_claims = set.new({ "openid"; "profile"; "email"; "address"; "phone" }); | 110 local openid_claims = set.new(); |
111 module:add_item("openid-claim", "openid"); | |
112 | |
113 module:handle_items("openid-claim", function(event) | |
114 authorization_server_metadata = nil; | |
115 openid_claims:add(event.item); | |
116 end, function() | |
117 authorization_server_metadata = nil; | |
118 openid_claims = set.new(module:get_host_items("openid-claim")); | |
119 end, true); | |
109 | 120 |
110 -- array -> array, array, array | 121 -- array -> array, array, array |
111 local function split_scopes(scope_list) | 122 local function split_scopes(scope_list) |
112 local claims, roles, unknown = array(), array(), array(); | 123 local claims, roles, unknown = array(), array(), array(); |
113 local all_roles = usermanager.get_all_roles(module.host); | 124 local all_roles = usermanager.get_all_roles(module.host); |
1077 return json.encode(oauth2_response); | 1088 return json.encode(oauth2_response); |
1078 end, 5); | 1089 end, 5); |
1079 | 1090 |
1080 -- OIDC Discovery | 1091 -- OIDC Discovery |
1081 | 1092 |
1093 function get_authorization_server_metadata() | |
1094 if authorization_server_metadata then | |
1095 return authorization_server_metadata; | |
1096 end | |
1097 authorization_server_metadata = { | |
1098 -- RFC 8414: OAuth 2.0 Authorization Server Metadata | |
1099 issuer = get_issuer(); | |
1100 authorization_endpoint = handle_authorization_request and module:http_url() .. "/authorize" or nil; | |
1101 token_endpoint = handle_token_grant and module:http_url() .. "/token" or nil; | |
1102 registration_endpoint = handle_register_request and module:http_url() .. "/register" or nil; | |
1103 scopes_supported = usermanager.get_all_roles | |
1104 and array(it.keys(usermanager.get_all_roles(module.host))):push("xmpp"):append(array(openid_claims:items())); | |
1105 response_types_supported = array(it.keys(response_type_handlers)); | |
1106 token_endpoint_auth_methods_supported = array({ "client_secret_post"; "client_secret_basic" }); | |
1107 op_policy_uri = module:get_option_string("oauth2_policy_url", nil); | |
1108 op_tos_uri = module:get_option_string("oauth2_terms_url", nil); | |
1109 revocation_endpoint = handle_revocation_request and module:http_url() .. "/revoke" or nil; | |
1110 revocation_endpoint_auth_methods_supported = array({ "client_secret_basic" }); | |
1111 code_challenge_methods_supported = array(it.keys(verifier_transforms)); | |
1112 grant_types_supported = array(it.keys(response_type_handlers)):map(tmap { | |
1113 token = "implicit"; | |
1114 code = "authorization_code"; | |
1115 }); | |
1116 response_modes_supported = array(it.keys(response_type_handlers)):map(tmap { token = "fragment"; code = "query" }); | |
1117 authorization_response_iss_parameter_supported = true; | |
1118 service_documentation = module:get_option_string("oauth2_service_documentation", "https://modules.prosody.im/mod_http_oauth2.html"); | |
1119 | |
1120 -- OpenID | |
1121 userinfo_endpoint = handle_register_request and module:http_url() .. "/userinfo" or nil; | |
1122 jwks_uri = nil; -- REQUIRED in OpenID Discovery but not in OAuth 2.0 Metadata | |
1123 id_token_signing_alg_values_supported = { "HS256" }; -- The algorithm RS256 MUST be included, but we use HS256 and client_secret as shared key. | |
1124 } | |
1125 return authorization_server_metadata; | |
1126 end | |
1127 | |
1082 module:provides("http", { | 1128 module:provides("http", { |
1083 name = "oauth2-discovery"; | 1129 name = "oauth2-discovery"; |
1084 default_path = "/.well-known/oauth-authorization-server"; | 1130 default_path = "/.well-known/oauth-authorization-server"; |
1085 cors = { enabled = true }; | 1131 cors = { enabled = true }; |
1086 route = { | 1132 route = { |
1087 ["GET"] = { | 1133 ["GET"] = function() |
1088 headers = { content_type = "application/json" }; | 1134 return { |
1089 body = json.encode { | 1135 headers = { content_type = "application/json" }; |
1090 -- RFC 8414: OAuth 2.0 Authorization Server Metadata | 1136 body = json.encode(get_authorization_server_metadata()); |
1091 issuer = get_issuer(); | 1137 } |
1092 authorization_endpoint = handle_authorization_request and module:http_url() .. "/authorize" or nil; | 1138 end |
1093 token_endpoint = handle_token_grant and module:http_url() .. "/token" or nil; | |
1094 registration_endpoint = handle_register_request and module:http_url() .. "/register" or nil; | |
1095 scopes_supported = usermanager.get_all_roles | |
1096 and array(it.keys(usermanager.get_all_roles(module.host))):push("xmpp"):append(array(openid_claims:items())); | |
1097 response_types_supported = array(it.keys(response_type_handlers)); | |
1098 token_endpoint_auth_methods_supported = array({ "client_secret_post"; "client_secret_basic" }); | |
1099 op_policy_uri = module:get_option_string("oauth2_policy_url", nil); | |
1100 op_tos_uri = module:get_option_string("oauth2_terms_url", nil); | |
1101 revocation_endpoint = handle_revocation_request and module:http_url() .. "/revoke" or nil; | |
1102 revocation_endpoint_auth_methods_supported = array({ "client_secret_basic" }); | |
1103 code_challenge_methods_supported = array(it.keys(verifier_transforms)); | |
1104 grant_types_supported = array(it.keys(response_type_handlers)):map(tmap { token = "implicit"; code = "authorization_code" }); | |
1105 response_modes_supported = array(it.keys(response_type_handlers)):map(tmap { token = "fragment"; code = "query" }); | |
1106 authorization_response_iss_parameter_supported = true; | |
1107 service_documentation = module:get_option_string("oauth2_service_documentation", "https://modules.prosody.im/mod_http_oauth2.html"); | |
1108 | |
1109 -- OpenID | |
1110 userinfo_endpoint = handle_register_request and module:http_url() .. "/userinfo" or nil; | |
1111 jwks_uri = nil; -- REQUIRED in OpenID Discovery but not in OAuth 2.0 Metadata | |
1112 id_token_signing_alg_values_supported = { "HS256" }; -- The algorithm RS256 MUST be included, but we use HS256 and client_secret as shared key. | |
1113 }; | |
1114 }; | |
1115 }; | 1139 }; |
1116 }); | 1140 }); |
1117 | 1141 |
1118 module:shared("tokenauth/oauthbearer_config").oidc_discovery_url = module:http_url("oauth2-discovery", "/.well-known/oauth-authorization-server"); | 1142 module:shared("tokenauth/oauthbearer_config").oidc_discovery_url = module:http_url("oauth2-discovery", "/.well-known/oauth-authorization-server"); |