Mercurial > prosody-modules
comparison mod_http_oauth2/mod_http_oauth2.lua @ 5367:93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Per https://openid.net/specs/openid-connect-registration-1_0.html
require that web applications use https:// and native applications must
use either http://localhost or a custom (non-https) URI.
Previous requirement that hostname matches that of client_uri is kept
for web applications.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Tue, 25 Apr 2023 19:49:41 +0200 |
parents | db4c66a1d24b |
children | 8b7d97f0ae8a |
comparison
equal
deleted
inserted
replaced
5366:db4c66a1d24b | 5367:93d445b26063 |
---|---|
655 "urn:ietf:params:oauth:grant-type:saml2-bearer"; | 655 "urn:ietf:params:oauth:grant-type:saml2-bearer"; |
656 }; | 656 }; |
657 }; | 657 }; |
658 default = { "authorization_code" }; | 658 default = { "authorization_code" }; |
659 }; | 659 }; |
660 application_type = { type = "string"; enum = { "native"; "web" }; default = "web" }; | |
660 response_types = { type = "array"; items = { type = "string"; enum = { "code"; "token" } }; default = { "code" } }; | 661 response_types = { type = "array"; items = { type = "string"; enum = { "code"; "token" } }; default = { "code" } }; |
661 client_name = { type = "string" }; | 662 client_name = { type = "string" }; |
662 client_uri = { type = "string"; format = "uri"; luaPattern = "^https:" }; | 663 client_uri = { type = "string"; format = "uri"; luaPattern = "^https:" }; |
663 logo_uri = { type = "string"; format = "uri"; luaPattern = "^https:" }; | 664 logo_uri = { type = "string"; format = "uri"; luaPattern = "^https:" }; |
664 scope = { type = "string" }; | 665 scope = { type = "string" }; |
675 ["^client_name#"] = { description = "Localized version of 'client_name'"; type = "string" }; | 676 ["^client_name#"] = { description = "Localized version of 'client_name'"; type = "string" }; |
676 ["^[a-z_]+_uri#"] = { type = "string"; format = "uri"; luaPattern = "^https:" }; | 677 ["^[a-z_]+_uri#"] = { type = "string"; format = "uri"; luaPattern = "^https:" }; |
677 }; | 678 }; |
678 } | 679 } |
679 | 680 |
681 local function redirect_uri_allowed(redirect_uri, client_uri, app_type) | |
682 local uri = url.parse(redirect_uri); | |
683 if app_type == "native" then | |
684 return uri.scheme == "http" and uri.host == "localhost" or uri.scheme ~= "https"; | |
685 elseif app_type == "web" then | |
686 return uri.scheme == "https" and uri.host == client_uri.host; | |
687 end | |
688 end | |
689 | |
680 function create_client(client_metadata) | 690 function create_client(client_metadata) |
681 if not schema.validate(registration_schema, client_metadata) then | 691 if not schema.validate(registration_schema, client_metadata) then |
682 return nil, oauth_error("invalid_request", "Failed schema validation."); | 692 return nil, oauth_error("invalid_request", "Failed schema validation."); |
683 end | 693 end |
684 | 694 |
693 if not client_uri or client_uri.scheme ~= "https" then | 703 if not client_uri or client_uri.scheme ~= "https" then |
694 return nil, oauth_error("invalid_request", "Missing, invalid or insecure client_uri"); | 704 return nil, oauth_error("invalid_request", "Missing, invalid or insecure client_uri"); |
695 end | 705 end |
696 | 706 |
697 for _, redirect_uri in ipairs(client_metadata.redirect_uris) do | 707 for _, redirect_uri in ipairs(client_metadata.redirect_uris) do |
698 local components = url.parse(redirect_uri); | 708 if not redirect_uri_allowed(redirect_uri, client_uri, client_metadata.application_type) then |
699 if not components or not components.scheme then | 709 return nil, oauth_error("invalid_request", "Invalid, insecure or inappropriate redirect URI."); |
700 return nil, oauth_error("invalid_request", "Invalid redirect URI."); | |
701 elseif components.scheme == "http" and components.host ~= "localhost" then | |
702 return nil, oauth_error("invalid_request", "Insecure redirect URI forbidden (except http://localhost)"); | |
703 elseif components.scheme == "https" and components.host ~= client_uri.host then | |
704 return nil, oauth_error("invalid_request", "Redirects must use the same hostname as client_uri"); | |
705 end | 710 end |
706 end | 711 end |
707 | 712 |
708 for field, prop_schema in pairs(registration_schema.properties) do | 713 for field, prop_schema in pairs(registration_schema.properties) do |
709 if field ~= "client_uri" and prop_schema.format == "uri" and client_metadata[field] then | 714 if field ~= "client_uri" and prop_schema.format == "uri" and client_metadata[field] then |