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 |
