comparison mod_http_oauth2/mod_http_oauth2.lua @ 5472:b80b6947b079

mod_http_oauth2: Always show early errors to user Before having validated the client_id, communicating an error back to the client via redirect would make this an open redirect, so we may just as well skip past that logic, and especially the warning log message.
author Kim Alvefur <zash@zash.se>
date Thu, 18 May 2023 13:43:17 +0200
parents d4d333cb75b2
children e4382f6e3564
comparison
equal deleted inserted replaced
5471:d4d333cb75b2 5472:b80b6947b079
595 response_type_handlers.code = nil; 595 response_type_handlers.code = nil;
596 response_type_handlers.token = nil; 596 response_type_handlers.token = nil;
597 grant_type_handlers.authorization_code = nil; 597 grant_type_handlers.authorization_code = nil;
598 end 598 end
599 599
600 local function render_error(err)
601 return render_page(templates.error, { error = err });
602 end
603
600 -- OAuth errors should be returned to the client if possible, i.e. by 604 -- OAuth errors should be returned to the client if possible, i.e. by
601 -- appending the error information to the redirect_uri and sending the 605 -- appending the error information to the redirect_uri and sending the
602 -- redirect to the user-agent. In some cases we can't do this, e.g. if 606 -- redirect to the user-agent. In some cases we can't do this, e.g. if
603 -- the redirect_uri is missing or invalid. In those cases, we render an 607 -- the redirect_uri is missing or invalid. In those cases, we render an
604 -- error directly to the user-agent. 608 -- error directly to the user-agent.
605 local function error_response(request, err) 609 local function error_response(request, err)
606 local q = request.url.query and http.formdecode(request.url.query); 610 local q = request.url.query and http.formdecode(request.url.query);
607 local redirect_uri = q and q.redirect_uri; 611 local redirect_uri = q and q.redirect_uri;
608 if not redirect_uri or not is_secure_redirect(redirect_uri) then 612 if not redirect_uri or not is_secure_redirect(redirect_uri) then
609 module:log("warn", "Missing or invalid redirect_uri <%s>, rendering error to user-agent", redirect_uri or ""); 613 module:log("warn", "Missing or invalid redirect_uri <%s>, rendering error to user-agent", redirect_uri or "");
610 return render_page(templates.error, { error = err }); 614 return render_error(err);
611 end 615 end
612 local redirect_query = url.parse(redirect_uri); 616 local redirect_query = url.parse(redirect_uri);
613 local sep = redirect_query.query and "&" or "?"; 617 local sep = redirect_query.query and "&" or "?";
614 redirect_uri = redirect_uri 618 redirect_uri = redirect_uri
615 .. sep .. http.formencode(err.extra.oauth2_response) 619 .. sep .. http.formencode(err.extra.oauth2_response)
678 end 682 end
679 683
680 local function handle_authorization_request(event) 684 local function handle_authorization_request(event)
681 local request = event.request; 685 local request = event.request;
682 686
687 -- Directly returning errors to the user before we have a validated client object
683 if not request.url.query then 688 if not request.url.query then
684 return error_response(request, oauth_error("invalid_request", "Missing query parameters")); 689 return render_error(oauth_error("invalid_request", "Missing query parameters"));
685 end 690 end
686 local params = http.formdecode(request.url.query); 691 local params = http.formdecode(request.url.query);
687 if not params then 692 if not params then
688 return error_response(request, oauth_error("invalid_request", "Invalid query parameters")); 693 return render_error(oauth_error("invalid_request", "Invalid query parameters"));
689 end 694 end
690 695
691 if not params.client_id then 696 if not params.client_id then
692 return oauth_error("invalid_request", "Missing 'client_id' parameter"); 697 return render_error(oauth_error("invalid_request", "Missing 'client_id' parameter"));
693 end 698 end
694 699
695 local ok, client = verify_client(params.client_id); 700 local ok, client = verify_client(params.client_id);
696 701
697 if not ok then 702 if not ok then
698 return oauth_error("invalid_request", "Invalid 'client_id' parameter"); 703 return render_error(oauth_error("invalid_request", "Invalid 'client_id' parameter"));
699 end 704 end
700 705
701 local client_response_types = set.new(array(client.response_types or { "code" })); 706 local client_response_types = set.new(array(client.response_types or { "code" }));
702 client_response_types = set.intersection(client_response_types, allowed_response_type_handlers); 707 client_response_types = set.intersection(client_response_types, allowed_response_type_handlers);
703 if not client_response_types:contains(params.response_type) then 708 if not client_response_types:contains(params.response_type) then
704 return oauth_error("invalid_client", "'response_type' not allowed"); 709 return error_response(request, oauth_error("invalid_client", "'response_type' not allowed"));
705 end 710 end
706 711
707 local requested_scopes = parse_scopes(params.scope or ""); 712 local requested_scopes = parse_scopes(params.scope or "");
708 if client.scope then 713 if client.scope then
709 local client_scopes = set.new(parse_scopes(client.scope)); 714 local client_scopes = set.new(parse_scopes(client.scope));