Software /
code /
prosody-modules
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 |
parent | 5471:d4d333cb75b2 |
child | 5473: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)); |