changeset 5367:93d445b26063

mod_http_oauth2: Validate redirect URI depending on application type Per https://openid.net/specs/openid-connect-registration-1_0.html require that web applications use https:// and native applications must use either http://localhost or a custom (non-https) URI. Previous requirement that hostname matches that of client_uri is kept for web applications.
author Kim Alvefur <zash@zash.se>
date Tue, 25 Apr 2023 19:49:41 +0200
parents db4c66a1d24b
children 165ccec95585
files mod_http_oauth2/mod_http_oauth2.lua
diffstat 1 files changed, 12 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/mod_http_oauth2/mod_http_oauth2.lua	Tue Apr 25 18:09:08 2023 +0200
+++ b/mod_http_oauth2/mod_http_oauth2.lua	Tue Apr 25 19:49:41 2023 +0200
@@ -657,6 +657,7 @@
 			};
 			default = { "authorization_code" };
 		};
+		application_type = { type = "string"; enum = { "native"; "web" }; default = "web" };
 		response_types = { type = "array"; items = { type = "string"; enum = { "code"; "token" } }; default = { "code" } };
 		client_name = { type = "string" };
 		client_uri = { type = "string"; format = "uri"; luaPattern = "^https:" };
@@ -677,6 +678,15 @@
 	};
 }
 
+local function redirect_uri_allowed(redirect_uri, client_uri, app_type)
+	local uri = url.parse(redirect_uri);
+	if app_type == "native" then
+		return uri.scheme == "http" and uri.host == "localhost" or uri.scheme ~= "https";
+	elseif app_type == "web" then
+		return uri.scheme == "https" and uri.host == client_uri.host;
+	end
+end
+
 function create_client(client_metadata)
 	if not schema.validate(registration_schema, client_metadata) then
 		return nil, oauth_error("invalid_request", "Failed schema validation.");
@@ -695,13 +705,8 @@
 	end
 
 	for _, redirect_uri in ipairs(client_metadata.redirect_uris) do
-		local components = url.parse(redirect_uri);
-		if not components or not components.scheme then
-			return nil, oauth_error("invalid_request", "Invalid redirect URI.");
-		elseif components.scheme == "http" and components.host ~= "localhost" then
-			return nil, oauth_error("invalid_request", "Insecure redirect URI forbidden (except http://localhost)");
-		elseif components.scheme == "https" and components.host ~= client_uri.host then
-			return nil, oauth_error("invalid_request", "Redirects must use the same hostname as client_uri");
+		if not redirect_uri_allowed(redirect_uri, client_uri, client_metadata.application_type) then
+			return nil, oauth_error("invalid_request", "Invalid, insecure or inappropriate redirect URI.");
 		end
 	end