Changeset

6282:7b3316ac24b3

mod_http_oauth2: Refactor client grant and response type checks Iterating over an array instead of creating a Set ought to create fewer short-lived tables. The arrays are usually very short so shouldn't be a performance issue. Moves validation earlier as to do less work before discovering that it can't proceed anyway.
author Kim Alvefur <zash@zash.se>
date Mon, 02 Jun 2025 22:21:44 +0200
parents 6281:9d88c3d9eea5
children 6283:10006e0519b9
files mod_http_oauth2/mod_http_oauth2.lua
diffstat 1 files changed, 24 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/mod_http_oauth2/mod_http_oauth2.lua	Mon Jun 02 20:55:20 2025 +0200
+++ b/mod_http_oauth2/mod_http_oauth2.lua	Mon Jun 02 22:21:44 2025 +0200
@@ -842,6 +842,15 @@
 	end
 end
 
+local function array_contains(haystack, needle)
+	for _, item in ipairs(haystack) do
+		if item == needle then
+			return true
+		end
+	end
+	return false
+end
+
 function handle_token_grant(event)
 	local credentials = get_request_credentials(event.request);
 
@@ -874,21 +883,13 @@
 
 
 	local grant_type = params.grant_type
-	local grant_handler = grant_type_handlers[grant_type];
-	if not grant_handler then
-		return oauth_error("invalid_request", "No such grant type.");
+	if not array_contains(client.grant_types or { "authorization_code" }, grant_type) then
+		return oauth_error("invalid_request", "'grant_type' not registered");
 	end
 
-	local grant_type_allowed = false;
-	for _, client_grant_type in ipairs(client.grant_types or { "authorization_code" }) do
-		if client_grant_type == grant_type then
-			grant_type_allowed = true;
-			break
-		end
-	end
-
-	if not grant_type_allowed then
-		return oauth_error("invalid_request", "'grant_type' not registered");
+	local grant_handler = grant_type_handlers[grant_type];
+	if not grant_handler then
+		return oauth_error("invalid_request", "'grant_type' not available");
 	end
 
 	return grant_handler(params, client);
@@ -922,10 +923,16 @@
 	end
 	-- From this point we know that redirect_uri is safe to use
 
-	local client_response_types = set.new(array(client.response_types or { "code" }));
-	client_response_types = set.intersection(client_response_types, allowed_response_type_handlers);
-	if not client_response_types:contains(params.response_type) then
-		return error_response(request, redirect_uri, oauth_error("invalid_client", "'response_type' not allowed"));
+	local response_type = params.response_type;
+	if not array_contains(client.response_types or { "code" }, response_type) then
+		return error_response(request, redirect_uri, oauth_error("invalid_client", "'response_type' not registered"));
+	end
+	if not allowed_response_type_handlers:contains(response_type) then
+		return error_response(request, redirect_uri, oauth_error("unsupported_response_type", "'response_type' not allowed"));
+	end
+	local response_handler = response_type_handlers[response_type];
+	if not response_handler then
+		return error_response(request, redirect_uri, oauth_error("unsupported_response_type"));
 	end
 
 	local requested_scopes = parse_scopes(params.scope or "");
@@ -1024,11 +1031,6 @@
 		nonce = params.nonce;
 		amr = auth_state.user.amr;
 	});
-	local response_type = params.response_type;
-	local response_handler = response_type_handlers[response_type];
-	if not response_handler then
-		return error_response(request, redirect_uri, oauth_error("unsupported_response_type"));
-	end
 	local ret = response_handler(client, params, user_jid, id_token);
 	if errors.is_err(ret) then
 		return error_response(request, redirect_uri, ret);