-
Notifications
You must be signed in to change notification settings - Fork 4.2k
fix(authentication): add Organization context validation in Merchant Create
and Merchant List
APIs
#8103
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
Conversation
…th Organization context validation
Changed Files
|
Merchant Create
and Merchant List
APIs with Organization context validationMerchant Create
and Merchant List
APIs
@@ -646,6 +670,7 @@ impl MerchantAccountCreateBridge for api::MerchantAccountCreate { | |||
state: &SessionState, | |||
key_store: domain::MerchantKeyStore, | |||
identifier: &id_type::MerchantId, | |||
_org_data: Option<authentication::AuthenticationDataWithOrg>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are we not using in v2? is it not required?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The trait MerchantAccountCreateBridge
is common to both v1 and v2, and we would not receive org_id from authentication in v2. The request body - MerchantAccountCreate
will mandatorily have the organization_id, which can be used to retrieve the organization in the v2 implementation.
@@ -223,7 +223,7 @@ pub async fn merchant_account_create( | |||
state, | |||
&req, | |||
new_request_payload_with_org_id, | |||
|state, _, req, _| create_merchant_account(state, req), | |||
|state, _, req, _| create_merchant_account(state, req, None), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why None
in v2 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For v2 create_merchant, V2AdminApiAuth
is the only authentication allowed, so we would not receive any org_id from auth, hence passing None.
let merchant = state | ||
.store() | ||
.find_merchant_account_by_merchant_id( | ||
key_manager_state, | ||
&stored_api_key.merchant_id, | ||
&key_store, | ||
) | ||
.await | ||
.to_not_found_response(errors::ApiErrorResponse::Unauthorized)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also be unexpected in a way: if we are able to find API key in our database, but unable to find the merchant account associated with the API key, then our database is possibly in an inconsistent state.
Not entirely sure if we should return 401 or another status code here, let's at least add a log line maybe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is how it is being handled in all types of API Key authentications currently. We are throwing 401 when the API Key is found, but merchant account is not found.
Should this be changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can take this up in a separate PR, for handling this in all such instances.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…ordea-sepa * 'main' of github.com:juspay/hyperswitch: (30 commits) chore(version): 2025.05.30.0 chore(ci): update postman ci credentials (#8172) chore(docs): remove old add_connector.md file (#8143) refactor: Payment Attempt as mandatory field in PaymentStatusData (#8126) fix(payment_link): sanitize embedded payment link data (#7736) chore(version): 2025.05.29.0 feat(analytics): Add ckh columns for 3ds intelligence analytics (#8136) refactor(debit_routing): Handle missing merchant_business_country by defaulting to US (#8141) chore(version): 2025.05.28.0 refactor(success_based): add support for exploration (#8158) feat(dynamic_routing): add get api for dynamic routing volume split (#8114) fix: incorrect payout_method_id in payouts table (#8107) feat(router): Enable client_secret auth for payments_get_intent [v2] (#8119) chore: address Rust 1.87.0 clippy lints (#8130) feat: list for dynamic routing (#8111) ci(cypress): fix mandates unsupported connectors (#8086) feat(connector): [Barclaycard] Implement Cards - Non 3DS flow (#8068) fix(authentication): add Organization context validation in `Merchant Create` and `Merchant List` APIs (#8103) feat(connector): [Worldpayxml] add card payment (#8076) feat(connector): Stripe revolut pay wallet integration (#8066) ...
Type of Change
Description
This PR introduces authentication validation checks in the following APIs to prevent unauthorized access across organizations:
List Merchant API
organization_id
in the query params as long as the token was valid.organization_id
provided in the query must match the one derived from the authentication context.Create Merchant API
Only the Admin API Key and configured fallback API Keys (set via env) can be used to create merchants.
organization_id
is not provided, a new organization is created, potentially allowing unauthorized org creation.organization_id
is manually provided, a user could create a merchant under any organization they should not have access to.Changes to Auth Flow
We have updated the authentication mechanism to now return:
Some(AuthenticationDataWithOrg { organization_id })
is returned when:None
is returned when:Additional Changes
Motivation and Context
The current implementations of the List and Create Merchant APIs do not enforce strict validation between the authenticated user's organization context and the
organization_id
passed in requests. This creates potential security risks where:This PR addresses those gaps by ensuring that all
organization_id
references are explicitly validated against the authenticated context.How did you test it?
Create Merchant API:
We can test the behavior of the Create Merchant API under two authentication modes:
Request:
Expected Response:
1. Admin API Key
organization_id
to create the merchant.2. Configured Fallback API Key (via env)
InvalidRequestData
.List Merchant API:
We can test the behavior of the List Merchant API under three authentication modes:
Request:
Expected Response:
1. Admin API Key
2. Configured Fallback API Key (via env)
InvalidRequestData
.3. JWT Authentication
Checklist
cargo +nightly fmt --all
cargo clippy