Software / code / prosody-modules
Comparison
mod_rest/mod_rest.lua @ 5960:d5e6617e47cc
mod_rest: Fix to allow case sensitive HTTP authentication scheme
Per RFC 9110 section 11
> It uses a case-insensitive token to identify the authentication scheme
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Sun, 14 Jul 2024 17:58:48 +0200 |
| parent | 5954:9bcc26406b47 |
| child | 5961:2739d3db591f |
comparison
equal
deleted
inserted
replaced
| 5959:ca3479c67e48 | 5960:d5e6617e47cc |
|---|---|
| 21 local tokens = module:depends("tokenauth"); | 21 local tokens = module:depends("tokenauth"); |
| 22 | 22 |
| 23 -- Lower than the default c2s size limit to account for possible JSON->XML size increase | 23 -- Lower than the default c2s size limit to account for possible JSON->XML size increase |
| 24 local stanza_size_limit = module:get_option_number("rest_stanza_size_limit", 1024 * 192); | 24 local stanza_size_limit = module:get_option_number("rest_stanza_size_limit", 1024 * 192); |
| 25 | 25 |
| 26 local auth_mechanisms = module:get_option_set("rest_auth_mechanisms", { "Basic", "Bearer" }); | 26 local auth_mechanisms = module:get_option_set("rest_auth_mechanisms", { "Basic", "Bearer" }) / string.lower; |
| 27 | 27 |
| 28 local www_authenticate_header; | 28 local www_authenticate_header; |
| 29 do | 29 do |
| 30 local header, realm = {}, module.host.."/"..module.name; | 30 local header, realm = {}, module.host.."/"..module.name; |
| 31 for mech in auth_mechanisms do | 31 for mech in auth_mechanisms do |
| 51 size = { code = 413; type = "modify"; condition = "resource-constraint", text = "Payload too large" }; | 51 size = { code = 413; type = "modify"; condition = "resource-constraint", text = "Payload too large" }; |
| 52 }); | 52 }); |
| 53 | 53 |
| 54 local function check_credentials(request) -- > session | boolean, error | 54 local function check_credentials(request) -- > session | boolean, error |
| 55 local auth_type, auth_data = string.match(request.headers.authorization, "^(%S+)%s(.+)$"); | 55 local auth_type, auth_data = string.match(request.headers.authorization, "^(%S+)%s(.+)$"); |
| 56 auth_type = auth_type:lower(); | |
| 56 if not (auth_type and auth_data) or not auth_mechanisms:contains(auth_type) then | 57 if not (auth_type and auth_data) or not auth_mechanisms:contains(auth_type) then |
| 57 return nil, post_errors.new("noauthz", { request = request }); | 58 return nil, post_errors.new("noauthz", { request = request }); |
| 58 end | 59 end |
| 59 | 60 |
| 60 if auth_type == "Basic" then | 61 if auth_type == "basic" then |
| 61 local creds = base64.decode(auth_data); | 62 local creds = base64.decode(auth_data); |
| 62 if not creds then | 63 if not creds then |
| 63 return nil, post_errors.new("malformauthz", { request = request }); | 64 return nil, post_errors.new("malformauthz", { request = request }); |
| 64 end | 65 end |
| 65 local username, password = string.match(creds, "^([^:]+):(.*)$"); | 66 local username, password = string.match(creds, "^([^:]+):(.*)$"); |
| 72 end | 73 end |
| 73 if not um.test_password(username, module.host, password) then | 74 if not um.test_password(username, module.host, password) then |
| 74 return false, post_errors.new("unauthz", { request = request }); | 75 return false, post_errors.new("unauthz", { request = request }); |
| 75 end | 76 end |
| 76 return { username = username; host = module.host }; | 77 return { username = username; host = module.host }; |
| 77 elseif auth_type == "Bearer" then | 78 elseif auth_type == "bearer" then |
| 78 if tokens.get_token_session then | 79 if tokens.get_token_session then |
| 79 return tokens.get_token_session(auth_data); | 80 return tokens.get_token_session(auth_data); |
| 80 else -- COMPAT w/0.12 | 81 else -- COMPAT w/0.12 |
| 81 local token_info = tokens.get_token_info(auth_data); | 82 local token_info = tokens.get_token_info(auth_data); |
| 82 if not token_info or not token_info.session then | 83 if not token_info or not token_info.session then |