Mercurial > prosody-modules
comparison mod_http_oauth2/mod_http_oauth2.lua @ 5554:90449babaa48
mod_http_oauth2: Make allowed locales configurable
Explicit > Implicit
Instead of allowing anything after #, allow only the explicitly
configured locales to be used.
Default to empty list because using these is not supported yet.
This potentially limits the size of the client_id, which is already
quite large. Nothing prevents clients from registering a whole
client_id per locale, which would not require translation support on
this side.
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Sat, 17 Jun 2023 19:03:32 +0200 |
| parents | 67152838afbc |
| children | d7fb8b266663 |
comparison
equal
deleted
inserted
replaced
| 5553:67152838afbc | 5554:90449babaa48 |
|---|---|
| 57 end | 57 end |
| 58 local data = assert(f:read("*a")); | 58 local data = assert(f:read("*a")); |
| 59 assert(f:close()); | 59 assert(f:close()); |
| 60 return data; | 60 return data; |
| 61 end | 61 end |
| 62 | |
| 63 local allowed_locales = module:get_option_array("allowed_oauth2_locales", {}); | |
| 64 -- TODO Allow translations or per-locale templates somehow. | |
| 62 | 65 |
| 63 local template_path = module:get_option_path("oauth2_template_path", "html"); | 66 local template_path = module:get_option_path("oauth2_template_path", "html"); |
| 64 local templates = { | 67 local templates = { |
| 65 login = read_file(template_path, "login.html", true); | 68 login = read_file(template_path, "login.html", true); |
| 66 consent = read_file(template_path, "consent.html", true); | 69 consent = read_file(template_path, "consent.html", true); |
| 934 jwks_uri = { type = "string"; format = "uri"; pattern = "^https:" }; | 937 jwks_uri = { type = "string"; format = "uri"; pattern = "^https:" }; |
| 935 jwks = { type = "object"; description = "JSON Web Key Set, RFC 7517" }; | 938 jwks = { type = "object"; description = "JSON Web Key Set, RFC 7517" }; |
| 936 software_id = { type = "string"; format = "uuid" }; | 939 software_id = { type = "string"; format = "uuid" }; |
| 937 software_version = { type = "string" }; | 940 software_version = { type = "string" }; |
| 938 }; | 941 }; |
| 939 luaPatternProperties = { | |
| 940 -- Localized versions of descriptive properties and URIs | |
| 941 ["^client_name#"] = { description = "Localized version of 'client_name'"; type = "string" }; | |
| 942 ["^[a-z_]+_uri#"] = { type = "string"; format = "uri" }; | |
| 943 }; | |
| 944 } | 942 } |
| 943 | |
| 944 -- Limit per-locale fields to allowed locales, partly to keep size of client_id | |
| 945 -- down, partly because we don't yet use them for anything. | |
| 946 -- Only relevant for user-visible strings and URIs. | |
| 947 if allowed_locales[1] then | |
| 948 local props = registration_schema.properties; | |
| 949 for _, locale in ipairs(allowed_locales) do | |
| 950 props["client_name#" .. locale] = props["client_name"]; | |
| 951 props["client_uri#" .. locale] = props["client_uri"]; | |
| 952 props["logo_uri#" .. locale] = props["logo_uri"]; | |
| 953 props["tos_uri#" .. locale] = props["tos_uri"]; | |
| 954 props["policy_uri#" .. locale] = props["policy_uri"]; | |
| 955 end | |
| 956 end | |
| 945 | 957 |
| 946 local function redirect_uri_allowed(redirect_uri, client_uri, app_type) | 958 local function redirect_uri_allowed(redirect_uri, client_uri, app_type) |
| 947 local uri = url.parse(redirect_uri); | 959 local uri = url.parse(redirect_uri); |
| 948 if not uri.scheme then | 960 if not uri.scheme then |
| 949 return false; -- no relative URLs | 961 return false; -- no relative URLs |
| 979 end | 991 end |
| 980 | 992 |
| 981 for field, prop_schema in pairs(registration_schema.properties) do | 993 for field, prop_schema in pairs(registration_schema.properties) do |
| 982 if field ~= "client_uri" and prop_schema.format == "uri" and client_metadata[field] then | 994 if field ~= "client_uri" and prop_schema.format == "uri" and client_metadata[field] then |
| 983 if not redirect_uri_allowed(client_metadata[field], client_uri, "web") then | 995 if not redirect_uri_allowed(client_metadata[field], client_uri, "web") then |
| 984 return nil, oauth_error("invalid_client_metadata", "Invalid, insecure or inappropriate informative URI"); | |
| 985 end | |
| 986 end | |
| 987 end | |
| 988 | |
| 989 for k, v in pairs(client_metadata) do | |
| 990 local base_k = k:match"^([^#]+)#" or k; | |
| 991 if not registration_schema.properties[base_k] or k:find"^client_uri#" then | |
| 992 -- Ignore and strip unknown extra properties | |
| 993 client_metadata[k] = nil; | |
| 994 elseif k:find"_uri#" then | |
| 995 -- Localized URIs should be secure too | |
| 996 if not redirect_uri_allowed(v, client_uri, "web") then | |
| 997 return nil, oauth_error("invalid_client_metadata", "Invalid, insecure or inappropriate informative URI"); | 996 return nil, oauth_error("invalid_client_metadata", "Invalid, insecure or inappropriate informative URI"); |
| 998 end | 997 end |
| 999 end | 998 end |
| 1000 end | 999 end |
| 1001 | 1000 |
| 1202 code = "authorization_code"; | 1201 code = "authorization_code"; |
| 1203 }); | 1202 }); |
| 1204 response_modes_supported = array(it.keys(response_type_handlers)):map(tmap { token = "fragment"; code = "query" }); | 1203 response_modes_supported = array(it.keys(response_type_handlers)):map(tmap { token = "fragment"; code = "query" }); |
| 1205 authorization_response_iss_parameter_supported = true; | 1204 authorization_response_iss_parameter_supported = true; |
| 1206 service_documentation = module:get_option_string("oauth2_service_documentation", "https://modules.prosody.im/mod_http_oauth2.html"); | 1205 service_documentation = module:get_option_string("oauth2_service_documentation", "https://modules.prosody.im/mod_http_oauth2.html"); |
| 1206 ui_locales_supported = allowed_locales[1] and allowed_locales; | |
| 1207 | 1207 |
| 1208 -- OpenID | 1208 -- OpenID |
| 1209 userinfo_endpoint = handle_register_request and module:http_url() .. "/userinfo" or nil; | 1209 userinfo_endpoint = handle_register_request and module:http_url() .. "/userinfo" or nil; |
| 1210 jwks_uri = nil; -- REQUIRED in OpenID Discovery but not in OAuth 2.0 Metadata | 1210 jwks_uri = nil; -- REQUIRED in OpenID Discovery but not in OAuth 2.0 Metadata |
| 1211 id_token_signing_alg_values_supported = { "HS256" }; -- The algorithm RS256 MUST be included, but we use HS256 and client_secret as shared key. | 1211 id_token_signing_alg_values_supported = { "HS256" }; -- The algorithm RS256 MUST be included, but we use HS256 and client_secret as shared key. |
