Changeset

6325:6ea80b73d8f2

mod_http_oauth2: Only require redirect URIs when using grant types that need it In the Device flow, no redirect URI is used because the client instead receives responses by polling. It is therefore unnecessary to enforce a requirement that these include redirect URI(s).
author Kim Alvefur <zash@zash.se>
date Thu, 03 Jul 2025 15:42:42 +0200
parents 6324:5dc4ec836ce2
children 6326:17d9533f7596
files mod_http_oauth2/mod_http_oauth2.lua
diffstat 1 files changed, 30 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/mod_http_oauth2/mod_http_oauth2.lua	Thu Jul 03 15:34:57 2025 +0200
+++ b/mod_http_oauth2/mod_http_oauth2.lua	Thu Jul 03 15:42:42 2025 +0200
@@ -375,7 +375,13 @@
 end
 
 local function get_redirect_uri(client, query_redirect_uri) -- record client, string : string
-	if not query_redirect_uri then
+	if query_redirect_uri == device_uri and client.grant_types then
+		if array_contains(client.grant_types, device_uri) then
+			return query_redirect_uri;
+		end
+		-- Tried to use device authorization flow without registering it.
+		return;
+	elseif not query_redirect_uri and client.redirect_uris then
 		if #client.redirect_uris ~= 1 then
 			-- Client registered multiple URIs, it needs specify which one to use
 			return;
@@ -383,15 +389,6 @@
 		-- When only a single URI is registered, that's the default
 		return client.redirect_uris[1];
 	end
-	if query_redirect_uri == device_uri and client.grant_types then
-		for _, grant_type in ipairs(client.grant_types) do
-			if grant_type == device_uri then
-				return query_redirect_uri;
-			end
-		end
-		-- Tried to use device authorization flow without registering it.
-		return;
-	end
 	-- Verify the client-provided URI matches one previously registered
 	for _, redirect_uri in ipairs(client.redirect_uris) do
 		if query_redirect_uri == redirect_uri then
@@ -1288,8 +1285,6 @@
 		-- These are shown to users in the template
 		"client_name";
 		"client_uri";
-		-- We need at least one redirect URI for things to work
-		"redirect_uris";
 	};
 	properties = {
 		redirect_uris = {
@@ -1306,8 +1301,10 @@
 					"http://localhost:8080/redirect";
 					"com.example.app:/redirect";
 					oob_uri;
-					device_uri;
 				};
+				["not"] = {
+					const = device_uri;
+				}
 			};
 		};
 		token_endpoint_auth_method = {
@@ -1479,9 +1476,12 @@
 		return nil, oauth_error("invalid_client_metadata", "Missing, invalid or insecure client_uri");
 	end
 
-	if not client_metadata.application_type and redirect_uri_allowed(client_metadata.redirect_uris[1], client_uri, "native") then
-		client_metadata.application_type = "native";
-		-- else defaults to "web"
+	if not client_metadata.application_type then
+		if client_metadata.redirect_uris and redirect_uri_allowed(client_metadata.redirect_uris[1], client_uri, "native") then
+			client_metadata.application_type = "native";
+		elseif array_contains(client_metadata.grant_types, device_uri) then
+			client_metadata.application_type = "native";
+		end
 	end
 
 	-- Fill in default values
@@ -1498,9 +1498,11 @@
 		end
 	end
 
-	for _, redirect_uri in ipairs(client_metadata.redirect_uris) do
-		if not redirect_uri_allowed(redirect_uri, client_uri, client_metadata.application_type) then
-			return nil, oauth_error("invalid_redirect_uri", "Invalid, insecure or inappropriate redirect URI.");
+	if client_metadata.redirect_uris then
+		for _, redirect_uri in ipairs(client_metadata.redirect_uris) do
+			if not redirect_uri_allowed(redirect_uri, client_uri, client_metadata.application_type) then
+				return nil, oauth_error("invalid_redirect_uri", "Invalid, insecure or inappropriate redirect URI.");
+			end
 		end
 	end
 
@@ -1521,6 +1523,15 @@
 		return nil, oauth_error("invalid_client_metadata", "Disallowed 'response_types' specified");
 	end
 
+
+	if not client_metadata.redirect_uris then
+		if grant_types:contains("authorization_code") then
+			return nil, oauth_error("invalid_client_metadata", "The 'authorization_code' grant requires 'redirect_uris' to be present.");
+		elseif grant_types:contains("implicit") then
+			return nil, oauth_error("invalid_client_metadata", "The 'implicit' grant requires 'redirect_uris' to be present.");
+		end
+	end
+
 	if grant_types:contains("authorization_code") and not response_types:contains("code") then
 		return nil, oauth_error("invalid_client_metadata", "Inconsistency between 'grant_types' and 'response_types'");
 	elseif grant_types:contains("implicit") and not response_types:contains("token") then