Mercurial > prosody-modules
comparison mod_http_oauth2/mod_http_oauth2.lua @ 5259:8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Sun, 19 Mar 2023 22:13:27 +0100 |
| parents | 9629971e307f |
| children | e73f364b5624 |
comparison
equal
deleted
inserted
replaced
| 5258:9629971e307f | 5259:8fba651b10ef |
|---|---|
| 634 software_id = { type = "string"; format = "uuid" }; | 634 software_id = { type = "string"; format = "uuid" }; |
| 635 software_version = { type = "string" }; | 635 software_version = { type = "string" }; |
| 636 }; | 636 }; |
| 637 } | 637 } |
| 638 | 638 |
| 639 local function handle_register_request(event) | 639 function create_client(client_metadata) |
| 640 local request = event.request; | |
| 641 local client_metadata = json.decode(request.body); | |
| 642 | |
| 643 if not schema.validate(registration_schema, client_metadata) then | 640 if not schema.validate(registration_schema, client_metadata) then |
| 644 return oauth_error("invalid_request", "Failed schema validation."); | 641 return nil, oauth_error("invalid_request", "Failed schema validation."); |
| 645 end | 642 end |
| 646 | 643 |
| 647 local client_uri = url.parse(client_metadata.client_uri); | 644 local client_uri = url.parse(client_metadata.client_uri); |
| 648 if not client_uri or client_uri.scheme ~= "https" then | 645 if not client_uri or client_uri.scheme ~= "https" then |
| 649 return oauth_error("invalid_request", "Missing, invalid or insecure client_uri"); | 646 return nil, oauth_error("invalid_request", "Missing, invalid or insecure client_uri"); |
| 650 end | 647 end |
| 651 | 648 |
| 652 for _, redirect_uri in ipairs(client_metadata.redirect_uris) do | 649 for _, redirect_uri in ipairs(client_metadata.redirect_uris) do |
| 653 local components = url.parse(redirect_uri); | 650 local components = url.parse(redirect_uri); |
| 654 if not components or not components.scheme then | 651 if not components or not components.scheme then |
| 655 return oauth_error("invalid_request", "Invalid redirect URI."); | 652 return nil, oauth_error("invalid_request", "Invalid redirect URI."); |
| 656 elseif components.scheme == "http" and components.host ~= "localhost" then | 653 elseif components.scheme == "http" and components.host ~= "localhost" then |
| 657 return oauth_error("invalid_request", "Insecure redirect URI forbidden (except http://localhost)"); | 654 return nil, oauth_error("invalid_request", "Insecure redirect URI forbidden (except http://localhost)"); |
| 658 elseif components.scheme == "https" and components.host ~= client_uri.host then | 655 elseif components.scheme == "https" and components.host ~= client_uri.host then |
| 659 return oauth_error("invalid_request", "Redirects must use the same hostname as client_uri"); | 656 return nil, oauth_error("invalid_request", "Redirects must use the same hostname as client_uri"); |
| 660 end | 657 end |
| 661 end | 658 end |
| 662 | 659 |
| 663 for field, prop_schema in pairs(registration_schema.properties) do | 660 for field, prop_schema in pairs(registration_schema.properties) do |
| 664 if field ~= "client_uri" and prop_schema.format == "uri" and client_metadata[field] then | 661 if field ~= "client_uri" and prop_schema.format == "uri" and client_metadata[field] then |
| 665 local components = url.parse(client_metadata[field]); | 662 local components = url.parse(client_metadata[field]); |
| 666 if components.scheme ~= "https" then | 663 if components.scheme ~= "https" then |
| 667 return oauth_error("invalid_request", "Insecure URI forbidden"); | 664 return nil, oauth_error("invalid_request", "Insecure URI forbidden"); |
| 668 end | 665 end |
| 669 if components.authority ~= client_uri.authority then | 666 if components.authority ~= client_uri.authority then |
| 670 return oauth_error("invalid_request", "Informative URIs must have the same hostname"); | 667 return nil, oauth_error("invalid_request", "Informative URIs must have the same hostname"); |
| 671 end | 668 end |
| 672 end | 669 end |
| 673 end | 670 end |
| 674 | 671 |
| 675 -- Ensure each signed client_id JWT is unique, short ID and issued at | 672 -- Ensure each signed client_id JWT is unique, short ID and issued at |
| 687 | 684 |
| 688 if not registration_options.accept_expired then | 685 if not registration_options.accept_expired then |
| 689 client_metadata.client_secret_expires_at = client_metadata.client_id_issued_at + (registration_options.default_ttl or 3600); | 686 client_metadata.client_secret_expires_at = client_metadata.client_id_issued_at + (registration_options.default_ttl or 3600); |
| 690 end | 687 end |
| 691 | 688 |
| 689 return client_metadata; | |
| 690 end | |
| 691 | |
| 692 local function handle_register_request(event) | |
| 693 local request = event.request; | |
| 694 local client_metadata, err = json.decode(request.body); | |
| 695 if err then | |
| 696 return oauth_error("invalid_request", "Invalid JSON"); | |
| 697 end | |
| 698 | |
| 699 local response, err = create_client(client_metadata); | |
| 700 if err then return err end | |
| 701 | |
| 692 return { | 702 return { |
| 693 status_code = 201; | 703 status_code = 201; |
| 694 headers = { content_type = "application/json" }; | 704 headers = { content_type = "application/json" }; |
| 695 body = json.encode(client_metadata); | 705 body = json.encode(response); |
| 696 }; | 706 }; |
| 697 end | 707 end |
| 698 | 708 |
| 699 if not registration_key then | 709 if not registration_key then |
| 700 module:log("info", "No 'oauth2_registration_key', dynamic client registration disabled") | 710 module:log("info", "No 'oauth2_registration_key', dynamic client registration disabled") |
