Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(payout_link): secure payout links using server side validations and client side headers #5219

Merged
merged 23 commits into from
Jul 17, 2024

Conversation

kashif-m
Copy link
Contributor

@kashif-m kashif-m commented Jul 5, 2024

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

This PR includes below changes -

  • adding allowed_domains field in payout link config
    • this is added at both business profile level and individual payout txns
    • business profile config is used as a fallback in case allowed_domains are not passed in payout link's create request
    • this is a required field in production env
  • server side validations for incoming render request
    • check Sec-Fetch-Dest [ref] for request source (must be iframe)
    • check Origin / Referer for the host of the incoming request (must match one in allowed_domains)
    • these are skipped if allowed_domains is not setup (only in non-production env)
  • client side headers
    • attach CSP header - frame-ancestors for directing which hosts can embed the links in an iframe [ref]
    • attach X-Frame header - similar to CSP, but for older browsers [ref] Removing this as it's outdated
  • update status UI for payout links

feat(generic_link): add allowed_domains in GenericLink response
feat(payout_link): add allowed_domains in payout_link_config (fallback profile config + payout request config)
feat(payout_link): consume meta headers for validating render request for payout links
feat(payout_link): consume CSP and X-Frame headers in the link's response

Additional Changes

  • This PR modifies the API contract
  • This PR modifies the database schema
  • This PR modifies application configuration/environment variables

Motivation and Context

How did you test it?

Tested locally using postman

  1. Update business profile's payout_link_config to include allowed_domains
curl --location 'http://localhost:8080/account/merchant_1721206540/business_profile/pro_iMeDAsjCBueHxdjCiZ9I' \
--header 'Content-Type: application/json' \
--header 'api-key: test_admin' \
--data '{
    "payout_link_config": {
        "allowed_domains": ["127.0.0.1:5500"]
    }
}'
  1. Create a payout link
curl --location 'http://localhost:8080/payouts/create' \
--header 'Content-Type: application/json' \
--header 'api-key: dev_Ew5ejag6iXMc80CDUUflU4daqTvm0wsMc1AgUo174U7iaV1GFvf8kkwt8LLCxDkT' \
--data '{
    "amount": 3000,
    "currency": "EUR",
    "billing": {
        "address": {
            "city": "Hoogeveen",
            "country": "NL",
            "line1": "Raadhuisplein",
            "line2": "92",
            "zip": "7901 BW",
            "state": "FL"
        },
        "phone": {
            "number": "0650242319",
            "country_code": "+31"
        }
    },
    "payout_link": true,
    "payout_link_config": {
        "theme": "#143F1E",
        "logo": "https://upload.wikimedia.org/wikipedia/commons/8/84/Spotify_icon.svg",
        "merchant_name": "Spotify"
    }
}'
  1. Try opening this link in a new tab (should not open)
  2. Open this inside an iframe (should open provided the allowed_domains and the iframe's host is same)

Test cases

cargo test --package common_utils --lib -- link_utils::domain_tests --show-output

image

Checklist

  • I formatted the code cargo +nightly fmt --all
  • I addressed lints thrown by cargo clippy
  • I reviewed the submitted code
  • I added unit tests for my changes where possible

kashif-m and others added 3 commits July 5, 2024 16:53
feat(generic_link): add allowed_domains in GenericLink response
feat(payout_link): add allowed_domains in payout_link_config (fallback profile config + payout request config)
feat(payout_link): consume meta headers for validating render request for payout links
feat(payout_link): consume CSP and X-Frame headers in the link's response
@hyperswitch-bot hyperswitch-bot bot added the M-api-contract-changes Metadata: This PR involves API contract changes label Jul 5, 2024
@kashif-m kashif-m linked an issue Jul 8, 2024 that may be closed by this pull request
2 tasks
@kashif-m kashif-m self-assigned this Jul 8, 2024
@kashif-m kashif-m marked this pull request as ready for review July 8, 2024 09:34
@kashif-m kashif-m requested review from a team as code owners July 8, 2024 09:35
Comment on lines +354 to +359
None => Err(report!(errors::ApiErrorResponse::AccessForbidden {
resource: "payout_link".to_string(),
}))
.attach_printable_lazy(|| {
format!(
"Access to payout_link [{}] is forbidden when sec-fetch-dest is not present in request headers",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we have a seperate forked UI for these failures doesn't look good throwing json error in user flow

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For later

Copy link
Contributor

@sahkal sahkal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be a bug in the payout link configs, since we are focusing on json. if one of the field is not sent in payment create and is set in business config, we will make the not sent value as None. Which is not the expected behavior i suppose.

crates/api_models/src/admin.rs Outdated Show resolved Hide resolved
crates/api_models/src/admin.rs Outdated Show resolved Hide resolved
crates/common_utils/src/link_utils.rs Outdated Show resolved Hide resolved
crates/router/src/core/admin.rs Outdated Show resolved Hide resolved
crates/common_utils/src/consts.rs Outdated Show resolved Hide resolved
crates/common_utils/src/link_utils.rs Show resolved Hide resolved
crates/router/src/core/payouts/validator.rs Outdated Show resolved Hide resolved
crates/router/src/types/api/admin.rs Outdated Show resolved Hide resolved
seekshiva
seekshiva previously approved these changes Jul 17, 2024
@hyperswitch-bot hyperswitch-bot bot added the M-database-changes Metadata: This PR involves database schema changes label Jul 17, 2024
@likhinbopanna likhinbopanna added this pull request to the merge queue Jul 17, 2024
Merged via the queue into main with commit 2d204c9 Jul 17, 2024
16 of 17 checks passed
@likhinbopanna likhinbopanna deleted the link_sec branch July 17, 2024 13:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
M-api-contract-changes Metadata: This PR involves API contract changes M-database-changes Metadata: This PR involves database schema changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FEATURE] Add security restrictions on the payout links
5 participants