feat(core/connector): introduce authentication token flow and add sepa bankdebit for nordea#8133
Merged
likhinbopanna merged 35 commits intomainfrom Aug 11, 2025
Merged
feat(core/connector): introduce authentication token flow and add sepa bankdebit for nordea#8133likhinbopanna merged 35 commits intomainfrom
likhinbopanna merged 35 commits intomainfrom
Conversation
02454ab to
070d7d2
Compare
475ca85 to
070d7d2
Compare
b1d0884 to
93b320a
Compare
5d8f1e9 to
6b8b2ed
Compare
6fc6c09 to
3468faf
Compare
i might have to do some refinements to this. but yeah, the connector still does not work as access token refactor is not done yet
3fbf75d
Sakilmostak
previously approved these changes
Aug 8, 2025
hrithikesh026
previously approved these changes
Aug 8, 2025
deepanshu-iiitu
previously approved these changes
Aug 8, 2025
…ordea-sepa * 'main' of github.com:juspay/hyperswitch: feat(core): Adding integration for webhooks through UCS (#8814) refactor(euclid): refactor logs for evaluation of equality for dynamic routing evaluate response (#8834) feat(connector): [SIFT] add Connector Template Code (#8488) feat(router): Add tokenization support for proxy and update the route for proxy (#8530) fix(ci): Fix Spell Check For CI Pull Request (#8857) feat(checkbook_io): connector integrate ACH (#8730) fix(connector): Change Refund Reason Type in Adyen (#8849)
eb45a3c
hrithikesh026
approved these changes
Aug 8, 2025
deepanshu-iiitu
approved these changes
Aug 8, 2025
Sakilmostak
approved these changes
Aug 9, 2025
14 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Type of Change
Description
Summary
This PR introduces Nordea as a new payment connector with support for SEPA bank debit payments. It also implements a new Authentication Token Flow mechanism that enables two-step OAuth authentication, which is required by certain connectors like Nordea.
Problem Statement
Some payment connectors require a more complex authentication process that involves:
The existing access token flow in Hyperswitch only supported direct access token generation, making it incompatible with connectors that require this two-step OAuth authentication process.
Solution
This PR introduces:
Implementation Details
Authentication Token Flow Architecture
The new authentication flow works as follows:
flowchart TD A[Payment Flow Initiated] --> B{Connector Supports<br/>Access Token?} B -->|No| Z[Continue with Payment<br/>No Access Token] B -->|Yes| C[Check Access Token Cache] C --> D{Access Token<br/>in Cache?} D -->|Yes| E[Use Cached Access Token] D -->|No| F{Connector Needs<br/>Authentication Token?} F -->|No| G[Create AccessTokenRequestData<br/>with ConnectorAuthType only] F -->|Yes| H[Authentication Token Flow] H --> I[Create AccessTokenAuthenticationRequestData<br/>from ConnectorAuthType] I --> J[Call execute_authentication_token] J --> K[POST /oauth/authorize<br/>with client credentials] K --> L{Authentication<br/>Successful?} L -->|No| M[Return Error] L -->|Yes| N[Receive AccessTokenAuthenticationResponse<br/>authorization code] N --> O[Create AccessTokenRequestData<br/>with ConnectorAuthType + AuthenticationToken] O --> P[Access Token Flow] G --> P P --> Q[Call refresh_connector_auth] Q --> R[POST /oauth/token<br/>exchange auth code for access token] R --> S{Access Token<br/>Successful?} S -->|No| T[Return Error] S -->|Yes| U[Receive AccessToken<br/>bearer token + expiry] U --> V[Cache Access Token<br/>with reduced expiry] V --> W[Return Access Token] E --> W W --> X[Use Access Token<br/>for Payment Requests] M --> Y[Payment Flow Fails] T --> Y X --> AA[Payment Flow Continues] Z --> AA style H fill:#e1f5fe style P fill:#f3e5f5 style I fill:#e8f5e8 style O fill:#e8f5e8 style K fill:#fff3e0 style R fill:#fff3e0 style V fill:#e8eaf6Key Components
authentication_token_for_token_creation()Nordea Connector Integration
Authentication: Implements OAuth 2.0 with eIDAS signature validation
Payment Methods: SEPA Credit Transfers (bank debit)
Supported Operations:
Not Supported:
Technical Implementation
Signature Generation: Implements eIDAS signature generation using RSA-SHA256 for API request signing
Auth Configuration: Uses
SignatureKeyauth type with:api_key: Client Secretkey1: Client IDapi_secret: eIDAS Private Key (base64 encoded)Request Signing: All requests include:
Payment Flow:
Changes Made
Core Authentication Infrastructure:
AccessTokenAuthenticationRequestDatastruct for auth token requestsAccessTokenAuthenticationResponsestruct for auth token responsesAccessTokenRequestDatato support both direct and exchange flowsexecute_authentication_tokenfunction for OAuth step 1Connector Implementation:
Configuration:
Testing
Unsupported features by Nordea
Breaking Changes
None - The authentication token flow is backward compatible and only activates for connectors that explicitly support it through the
authentication_token_for_token_creation()method.Additional Changes
Motivation and Context
New connector Nordea SEPA integration. Closes #8134.
How did you test it?
MCA
{ "connector_type": "payment_processor", "connector_name": "nordea", "connector_label": "nordea_US_default", "merchant_connector_id": "mca_UWrnV7EnGkfVapwuHOAM", "profile_id": "pro_892QTRQ3W6mWykBeSXDQ", "connector_account_details": { "auth_type": "SignatureKey", "api_key": "client_secret", "key1": "client_id", "api_secret": "decrypted_certificate" }, "payment_methods_enabled": [ { "payment_method": "bank_debit", "payment_method_types": [ { "payment_method_type": "sepa", "payment_experience": null, "card_networks": null, "accepted_currencies": null, "accepted_countries": null, "minimum_amount": 1, "maximum_amount": 68607706, "recurring_enabled": true, "installment_payment_enabled": true } ] } ], "connector_webhook_details": null, "metadata": { "creditor_account_type": "IBAN", "creditor_account_value": "FI7473834510057469", "creditor_beneficiary_name": "Test Merchant" }, "test_mode": false, "disabled": false, "frm_configs": null, "business_country": "US", "business_label": "default", "business_sub_label": null, "applepay_verified_domains": null, "pm_auth_config": null, "status": "active", "additional_merchant_data": null, "connector_wallets_details": null }Payment Create
{ "payment_id": "pay_GJDKAKdDxM4bQ8xX0anw", "merchant_id": "postman_merchant_GHAction_1752842696", "status": "requires_payment_method", "amount": 10400, "net_amount": 10400, "shipping_cost": null, "amount_capturable": 0, "amount_received": null, "connector": null, "client_secret": "pay_GJDKAKdDxM4bQ8xX0anw_secret_TL3I7uzVd7IA4uvwkPqh", "created": "2025-07-18T12:45:03.009Z", "currency": "EUR", "customer_id": "customer", "customer": { "id": "customer", "name": null, "email": "guesjhvghht@example.com", "phone": "999999999", "phone_country_code": "+1" }, "description": "Its my first payment request", "refunds": null, "disputes": null, "mandate_id": null, "mandate_data": null, "setup_future_usage": null, "off_session": null, "capture_on": null, "capture_method": "automatic", "payment_method": null, "payment_method_data": null, "payment_token": null, "shipping": { "address": { "city": "San Fransico", "country": "FI", "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "zip": "94122", "state": "California", "first_name": "PiX", "last_name": null }, "phone": null, "email": null }, "billing": { "address": { "city": "San Fransico", "country": "FI", "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "zip": "94122", "state": "California", "first_name": "PiX", "last_name": "THE" }, "phone": null, "email": null }, "order_details": null, "email": "guesjhvghht@example.com", "name": null, "phone": "999999999", "return_url": "https://duck.com/", "authentication_type": "three_ds", "statement_descriptor_name": "joseph", "statement_descriptor_suffix": "JS", "next_action": null, "cancellation_reason": null, "error_code": null, "error_message": null, "unified_code": null, "unified_message": null, "payment_experience": null, "payment_method_type": null, "connector_label": null, "business_country": null, "business_label": "default", "business_sub_label": null, "allowed_payment_method_types": null, "ephemeral_key": { "customer_id": "customer", "created_at": 1752842702, "expires": 1752846302, "secret": "epk_d55a0599354449ebafda40a1f4989778" }, "manual_retry_allowed": null, "connector_transaction_id": null, "frm_message": null, "metadata": { "udf1": "value1", "login_date": "2019-09-10T10:11:12Z", "new_customer": "true" }, "connector_metadata": null, "feature_metadata": null, "reference_id": null, "payment_link": null, "profile_id": "pro_892QTRQ3W6mWykBeSXDQ", "surcharge_details": null, "attempt_count": 1, "merchant_decision": null, "merchant_connector_id": null, "incremental_authorization_allowed": null, "authorization_count": null, "incremental_authorizations": null, "external_authentication_details": null, "external_3ds_authentication_attempted": false, "expires_on": "2025-07-18T13:00:03.008Z", "fingerprint": null, "browser_info": { "language": "en-GB", "time_zone": -330, "ip_address": "208.127.127.193", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0", "color_depth": 24, "java_enabled": true, "screen_width": 1280, "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "screen_height": 720, "java_script_enabled": true }, "payment_method_id": null, "payment_method_status": null, "updated": "2025-07-18T12:45:03.075Z", "split_payments": null, "frm_metadata": null, "extended_authorization_applied": null, "capture_before": null, "merchant_order_reference_id": null, "order_tax_amount": null, "connector_mandate_id": null, "card_discovery": null, "force_3ds_challenge": false, "force_3ds_challenge_trigger": false, "issuer_error_code": null, "issuer_error_message": null, "is_iframe_redirection_enabled": null, "whole_connector_response": null }Payment Confirm
{ "payment_id": "pay_GJDKAKdDxM4bQ8xX0anw", "merchant_id": "postman_merchant_GHAction_1752842696", "status": "requires_customer_action", "amount": 10400, "net_amount": 10400, "shipping_cost": null, "amount_capturable": 10400, "amount_received": null, "connector": "nordea", "client_secret": "pay_GJDKAKdDxM4bQ8xX0anw_secret_TL3I7uzVd7IA4uvwkPqh", "created": "2025-07-18T12:45:03.009Z", "currency": "EUR", "customer_id": "customer", "customer": { "id": "customer", "name": null, "email": "guesjhvghht@example.com", "phone": "999999999", "phone_country_code": "+1" }, "description": "Its my first payment request", "refunds": null, "disputes": null, "mandate_id": null, "mandate_data": null, "setup_future_usage": null, "off_session": null, "capture_on": null, "capture_method": "automatic", "payment_method": "bank_debit", "payment_method_data": { "bank_debit": { "sepa": { "iban": "FI659********93470", "bank_account_holder_name": null } }, "billing": null }, "payment_token": null, "shipping": { "address": { "city": "San Fransico", "country": "FI", "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "zip": "94122", "state": "California", "first_name": "PiX", "last_name": null }, "phone": null, "email": null }, "billing": { "address": { "city": "San Fransico", "country": "FI", "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "zip": "94122", "state": "California", "first_name": "PiX", "last_name": "THE" }, "phone": null, "email": null }, "order_details": null, "email": "guesjhvghht@example.com", "name": null, "phone": "999999999", "return_url": "https://duck.com/", "authentication_type": "three_ds", "statement_descriptor_name": "joseph", "statement_descriptor_suffix": "JS", "next_action": { "type": "redirect_to_url", "redirect_to_url": "http://localhost:8080/payments/redirect/pay_GJDKAKdDxM4bQ8xX0anw/postman_merchant_GHAction_1752842696/pay_GJDKAKdDxM4bQ8xX0anw_1" }, "cancellation_reason": null, "error_code": null, "error_message": null, "unified_code": null, "unified_message": null, "payment_experience": null, "payment_method_type": "sepa", "connector_label": null, "business_country": null, "business_label": "default", "business_sub_label": null, "allowed_payment_method_types": null, "ephemeral_key": null, "manual_retry_allowed": null, "connector_transaction_id": "c14b226e-dfc1-4458-a477-a7b3ee4387fd", "frm_message": null, "metadata": { "udf1": "value1", "login_date": "2019-09-10T10:11:12Z", "new_customer": "true" }, "connector_metadata": null, "feature_metadata": null, "reference_id": "pay_GJDKAKdDxM4bQ8xX0anw_1", "payment_link": null, "profile_id": "pro_892QTRQ3W6mWykBeSXDQ", "surcharge_details": null, "attempt_count": 1, "merchant_decision": null, "merchant_connector_id": "mca_UWrnV7EnGkfVapwuHOAM", "incremental_authorization_allowed": null, "authorization_count": null, "incremental_authorizations": null, "external_authentication_details": null, "external_3ds_authentication_attempted": false, "expires_on": "2025-07-18T13:00:03.008Z", "fingerprint": null, "browser_info": { "os_type": null, "language": null, "time_zone": null, "ip_address": "::1", "os_version": null, "user_agent": null, "color_depth": null, "device_model": null, "java_enabled": null, "screen_width": null, "accept_header": null, "screen_height": null, "accept_language": "en", "java_script_enabled": null }, "payment_method_id": null, "payment_method_status": null, "updated": "2025-07-18T12:45:06.878Z", "split_payments": null, "frm_metadata": null, "extended_authorization_applied": null, "capture_before": null, "merchant_order_reference_id": null, "order_tax_amount": null, "connector_mandate_id": null, "card_discovery": null, "force_3ds_challenge": false, "force_3ds_challenge_trigger": false, "issuer_error_code": null, "issuer_error_message": null, "is_iframe_redirection_enabled": null, "whole_connector_response": null }Redirection
Retrieve
{ "payment_id": "pay_GJDKAKdDxM4bQ8xX0anw", "merchant_id": "postman_merchant_GHAction_1752842696", "status": "succeeded", "amount": 10400, "net_amount": 10400, "shipping_cost": null, "amount_capturable": 0, "amount_received": 10400, "connector": "nordea", "client_secret": "pay_GJDKAKdDxM4bQ8xX0anw_secret_TL3I7uzVd7IA4uvwkPqh", "created": "2025-07-18T12:45:03.009Z", "currency": "EUR", "customer_id": "customer", "customer": { "id": "customer", "name": null, "email": "guesjhvghht@example.com", "phone": "999999999", "phone_country_code": "+1" }, "description": "Its my first payment request", "refunds": null, "disputes": null, "mandate_id": null, "mandate_data": null, "setup_future_usage": null, "off_session": null, "capture_on": null, "capture_method": "automatic", "payment_method": "bank_debit", "payment_method_data": { "bank_debit": { "sepa": { "iban": "FI659********93470", "bank_account_holder_name": null } }, "billing": null }, "payment_token": null, "shipping": { "address": { "city": "San Fransico", "country": "FI", "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "zip": "94122", "state": "California", "first_name": "PiX", "last_name": null }, "phone": null, "email": null }, "billing": { "address": { "city": "San Fransico", "country": "FI", "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "zip": "94122", "state": "California", "first_name": "PiX", "last_name": "THE" }, "phone": null, "email": null }, "order_details": null, "email": "guesjhvghht@example.com", "name": null, "phone": "999999999", "return_url": "https://duck.com/", "authentication_type": "three_ds", "statement_descriptor_name": "joseph", "statement_descriptor_suffix": "JS", "next_action": null, "cancellation_reason": null, "error_code": null, "error_message": null, "unified_code": null, "unified_message": null, "payment_experience": null, "payment_method_type": "sepa", "connector_label": null, "business_country": null, "business_label": "default", "business_sub_label": null, "allowed_payment_method_types": null, "ephemeral_key": null, "manual_retry_allowed": false, "connector_transaction_id": "c14b226e-dfc1-4458-a477-a7b3ee4387fd", "frm_message": null, "metadata": { "udf1": "value1", "login_date": "2019-09-10T10:11:12Z", "new_customer": "true" }, "connector_metadata": null, "feature_metadata": null, "reference_id": "pay_GJDKAKdDxM4bQ8xX0anw_1", "payment_link": null, "profile_id": "pro_892QTRQ3W6mWykBeSXDQ", "surcharge_details": null, "attempt_count": 1, "merchant_decision": null, "merchant_connector_id": "mca_UWrnV7EnGkfVapwuHOAM", "incremental_authorization_allowed": null, "authorization_count": null, "incremental_authorizations": null, "external_authentication_details": null, "external_3ds_authentication_attempted": false, "expires_on": "2025-07-18T13:00:03.008Z", "fingerprint": null, "browser_info": { "os_type": null, "language": null, "time_zone": null, "ip_address": "::1", "os_version": null, "user_agent": null, "color_depth": null, "device_model": null, "java_enabled": null, "screen_width": null, "accept_header": null, "screen_height": null, "accept_language": "en", "java_script_enabled": null }, "payment_method_id": null, "payment_method_status": null, "updated": "2025-07-18T12:45:16.869Z", "split_payments": null, "frm_metadata": null, "extended_authorization_applied": null, "capture_before": null, "merchant_order_reference_id": null, "order_tax_amount": null, "connector_mandate_id": null, "card_discovery": null, "force_3ds_challenge": false, "force_3ds_challenge_trigger": false, "issuer_error_code": null, "issuer_error_message": null, "is_iframe_redirection_enabled": null, "whole_connector_response": null }Cypress
WILL INTRODUCE IN NEXT PR.
Checklist
cargo +nightly fmt --alljust clippy && just clippy_v2