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.