# HG changeset patch # User Kim Alvefur # Date 1748895704 -7200 # Node ID 7b3316ac24b34d40c3bbad4d2d60dc26f0ecb9af # Parent 9d88c3d9eea59bf4c72b6c3418f82bcc6e4bb0fd 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. diff -r 9d88c3d9eea5 -r 7b3316ac24b3 mod_http_oauth2/mod_http_oauth2.lua --- 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);