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