Software / code / prosody-modules
Comparison
mod_http_oauth2/mod_http_oauth2.lua @ 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 |
| parent | 6281:9d88c3d9eea5 |
| child | 6285:b460b2a65f0b |
comparison
equal
deleted
inserted
replaced
| 6281:9d88c3d9eea5 | 6282:7b3316ac24b3 |
|---|---|
| 840 else | 840 else |
| 841 module:log("debug", "Challenge method %q enabled", handler_type); | 841 module:log("debug", "Challenge method %q enabled", handler_type); |
| 842 end | 842 end |
| 843 end | 843 end |
| 844 | 844 |
| 845 local function array_contains(haystack, needle) | |
| 846 for _, item in ipairs(haystack) do | |
| 847 if item == needle then | |
| 848 return true | |
| 849 end | |
| 850 end | |
| 851 return false | |
| 852 end | |
| 853 | |
| 845 function handle_token_grant(event) | 854 function handle_token_grant(event) |
| 846 local credentials = get_request_credentials(event.request); | 855 local credentials = get_request_credentials(event.request); |
| 847 | 856 |
| 848 event.response.headers.content_type = "application/json"; | 857 event.response.headers.content_type = "application/json"; |
| 849 event.response.headers.cache_control = "no-store"; | 858 event.response.headers.cache_control = "no-store"; |
| 872 return oauth_error("invalid_client", "incorrect credentials"); | 881 return oauth_error("invalid_client", "incorrect credentials"); |
| 873 end | 882 end |
| 874 | 883 |
| 875 | 884 |
| 876 local grant_type = params.grant_type | 885 local grant_type = params.grant_type |
| 886 if not array_contains(client.grant_types or { "authorization_code" }, grant_type) then | |
| 887 return oauth_error("invalid_request", "'grant_type' not registered"); | |
| 888 end | |
| 889 | |
| 877 local grant_handler = grant_type_handlers[grant_type]; | 890 local grant_handler = grant_type_handlers[grant_type]; |
| 878 if not grant_handler then | 891 if not grant_handler then |
| 879 return oauth_error("invalid_request", "No such grant type."); | 892 return oauth_error("invalid_request", "'grant_type' not available"); |
| 880 end | |
| 881 | |
| 882 local grant_type_allowed = false; | |
| 883 for _, client_grant_type in ipairs(client.grant_types or { "authorization_code" }) do | |
| 884 if client_grant_type == grant_type then | |
| 885 grant_type_allowed = true; | |
| 886 break | |
| 887 end | |
| 888 end | |
| 889 | |
| 890 if not grant_type_allowed then | |
| 891 return oauth_error("invalid_request", "'grant_type' not registered"); | |
| 892 end | 893 end |
| 893 | 894 |
| 894 return grant_handler(params, client); | 895 return grant_handler(params, client); |
| 895 end | 896 end |
| 896 | 897 |
| 920 if not redirect_uri then | 921 if not redirect_uri then |
| 921 return render_error(oauth_error("invalid_request", "Invalid 'redirect_uri' parameter")); | 922 return render_error(oauth_error("invalid_request", "Invalid 'redirect_uri' parameter")); |
| 922 end | 923 end |
| 923 -- From this point we know that redirect_uri is safe to use | 924 -- From this point we know that redirect_uri is safe to use |
| 924 | 925 |
| 925 local client_response_types = set.new(array(client.response_types or { "code" })); | 926 local response_type = params.response_type; |
| 926 client_response_types = set.intersection(client_response_types, allowed_response_type_handlers); | 927 if not array_contains(client.response_types or { "code" }, response_type) then |
| 927 if not client_response_types:contains(params.response_type) then | 928 return error_response(request, redirect_uri, oauth_error("invalid_client", "'response_type' not registered")); |
| 928 return error_response(request, redirect_uri, oauth_error("invalid_client", "'response_type' not allowed")); | 929 end |
| 930 if not allowed_response_type_handlers:contains(response_type) then | |
| 931 return error_response(request, redirect_uri, oauth_error("unsupported_response_type", "'response_type' not allowed")); | |
| 932 end | |
| 933 local response_handler = response_type_handlers[response_type]; | |
| 934 if not response_handler then | |
| 935 return error_response(request, redirect_uri, oauth_error("unsupported_response_type")); | |
| 929 end | 936 end |
| 930 | 937 |
| 931 local requested_scopes = parse_scopes(params.scope or ""); | 938 local requested_scopes = parse_scopes(params.scope or ""); |
| 932 if client.scope then | 939 if client.scope then |
| 933 local client_scopes = set.new(parse_scopes(client.scope)); | 940 local client_scopes = set.new(parse_scopes(client.scope)); |
| 1022 aud = params.client_id; | 1029 aud = params.client_id; |
| 1023 auth_time = auth_state.user.iat; | 1030 auth_time = auth_state.user.iat; |
| 1024 nonce = params.nonce; | 1031 nonce = params.nonce; |
| 1025 amr = auth_state.user.amr; | 1032 amr = auth_state.user.amr; |
| 1026 }); | 1033 }); |
| 1027 local response_type = params.response_type; | |
| 1028 local response_handler = response_type_handlers[response_type]; | |
| 1029 if not response_handler then | |
| 1030 return error_response(request, redirect_uri, oauth_error("unsupported_response_type")); | |
| 1031 end | |
| 1032 local ret = response_handler(client, params, user_jid, id_token); | 1034 local ret = response_handler(client, params, user_jid, id_token); |
| 1033 if errors.is_err(ret) then | 1035 if errors.is_err(ret) then |
| 1034 return error_response(request, redirect_uri, ret); | 1036 return error_response(request, redirect_uri, ret); |
| 1035 end | 1037 end |
| 1036 return ret; | 1038 return ret; |