Skip to main content

API Authorization

Access authorization API consists of endpoints that enable TPP to initiate an authentication and authorization flow, whereby the PSU authorises account access. Ultimately the TPP receives an access token that can be used in AIS, PIS and CFS calls as applicable.
To access all APIs, it is necessary to establish a consent between the TPP, the PSU and the ASPSP.

The sequence diagram below shows the HTTP requests made by TPP and PSU during authorization flow for AIS, PIS or CFS APIs. The authorization flow uses tls_client_auth for authentication and includes:

  • [2] OAuth2 Client Credentials grant for issuing TPP access token.
  • [4]-[8] OpenID Connect Hybrid Flow for getting PSU consent and issuing access tokens for PSU account data access.
Sequence diagram showing the API authorization flow between PSU, TPP and Danske Bank

Detailed step description:

[1] PSU calls TPP

This flow begins with a PSU consenting to allow an API to access API data, make a payment or  respond to confirmation of funds requests.

[2] TPP retrieves a Client Credentials Grant token

To create a consent the TPP first needs to request a Client Credentials Grant token by calling the token endpoint specified in the OpenId configuration (token_endpoint). The request should be a x-www-form-urlencoded POST with the following parameters

A sample request may look like this:

  • grant_type - client_credentials. (read more)
  • scope - should contain a scope the TPP has access to: for Payment InitiationAPI the parameter MUST contain the “payments” keyword, for Account/Transaction API the parameter MUST contain the “accounts” keyword, for Confirmation of Funds API the parameter MUST contain the “fundsconfirmations”. (read more)
  • client_id - the id received with the registration response. (read more)

Example request body:

grant_type=client_credentials&scope=accounts&client_id=1234567890

Example response:

{
  "token_type": "Bearer",
  "access_token": "A****",
  "metadata": "m:",
  "expires_in": 3600,
  "consented_on": 1588933990,
  "scope": "accounts"
}

The access_token received should be used for all operations that do not require PSU authorization: creating, retrieving and removing consents, retrieving event data and so on. Access token should be included in the Authorization header in the POST request:

Authorization: Bearer <access token>

Token is valid for 1h.

TPP creates an account access consent describing what kind of information it wants to retrieve. For Payment Initiation API /payments, for Account and Transaction API /account-access-consents and for Confirmation of Funds /funds-confirmation-consents.
Request payload is a json. The payload syntax is specified in each APIs reference section. Connecting to the consent endpoints requires a mutual TLS connection with the network certificate used during TPP registration.
The response contains consentId – a unique resource identifier that should be stored for later use.

[4] TPP initiates PSU authorization

TPP sends a redirect response to PSU (Http 302). The redirect initialises the customer authorization procedure as described in OpenID Connect Hybrid Flow (link). Hybrid flow is an extension of OAuth2 Authorization Code Flow (link) that allows to return additional information together with the authorization code. A sample redirect response might look like this:

HTTP/1.1 302 Found
Location: https://sandbox-obp-api.danskebank.com/sandbox-open-banking/external/private/oauth2/authorize?client_id=c4040e4f1614f9da3d37730aeb5030ee9f8b24d7bc08c80e2ea561d81ba94688&scope=openid%20accounts&response_type=code%20id_token&redirect_uri=https://tppapp-obrw-api-pkob-dev.paas-dblan.danskenet.net/authorize&request=eyJraWQiOiJad2xUdEthNHZ4NG9vVmJ6ZlFLV25YQ3Mtb1EiLCJhbGciOiJSUzI1NiJ9.eyJtYXhfYWdlIjo4NjQwMCwiYXVkIjoiaHR0cHM6XC9cL29icC1hcGkuZGFuc2tlYmFuay5jb20iLCJzY29wZSI6Im9wZW5pZCBhY2NvdW50cyIsImlzcyI6ImM0MDQwZTRmMTYxNGY5ZGEzZDM3NzMwYWViNTAzMGVlOWY4YjI0ZDdiYzA4YzgwZTJlYTU2MWQ4MWJhOTQ2ODgiLCJjbGFpbXMiOnsiaWRfdG9rZW4iOnsiYWNyIjp7ImVzc2VudGlhbCI6dHJ1ZX0sIm9wZW5iYW5raW5nX2ludGVudF9pZCI6eyJ2YWx1ZSI6InVybjphY2NvdW50czp2Mzo0ZGJhYjVlZS1jNzE4LTQzOTYtYjRjMC01ZTgxNDljNTY1ZjAiLCJlc3NlbnRpYWwiOnRydWV9fX0sInJlc3BvbnNlX3R5cGUiOiJjb2RlIGlkX3Rva2VuIiwicmVkaXJlY3RfdXJpIjoiaHR0cHM6XC9cL3RwcGFwcC1vYnJ3LWFwaS1wa29iLWRldi5wYWFzLWRibGFuLmRhbnNrZW5ldC5uZXRcL2F1dGhvcml6ZSIsInN0YXRlIjoic3RhdGU6NDI0ODM6NDA0MjIxOTIxOTQ1ODU1Iiwibm9uY2UiOiJiMjc2Y2VjMC0zYzZhLTRkZTItYTAyYS02NTM2MTUwNWY2MjAiLCJjbGllbnRfaWQiOiJjNDA0MGU0ZjE2MTRmOWRhM2QzNzczMGFlYjUwMzBlZTlmOGIyNGQ3YmMwOGM4MGUyZWE1NjFkODFiYTk0Njg4In0.k1xYbfKIE5T-v_A6A_HK2F--e9JY_ig4Vw6ikmEOOm453KDlrhdhRc7ncSS2Ut4P_ruj6yA8NrRv87SrFonMo5kxr82R6--HFJGeVRVPZG9VWnBo0hlQ38OBKS3upV-djctMeH6hDJOg3wUu7GME048v_s4wQOwN2HlH_3u2zUnQM6i2iSIp1IJBI_nZtfBryAcyOyir6feS2tHoMMOWHt5BCX9lblzDHayr3ySa2I2Rps-y8KfNm7ZUgzUC589XaBZD4HYGcwEJaVpxYynofFhNVNmtXmPz2iFnMBV8Mh3Hq72DFynq8UJOi2MetAry4M_LJ1XSRsI1T1b5-E3j2w

A detailed description of query parameters included in the Location header url is listed here: link. A brief summary of the query parameters used is below:

URL Parameters

  • request - see JWT request description below this paragraph.
  • client_id - Client Id received from registration response (read more).
  • redirect_uri - The redirect url to which the authorization code should be sent. The url should match the values provided during TPP onboarding. Example: https//tpp.domain.com/callback?optional=parameter
  • scope - openid and the scope corresponding to the consent being authorized, for Payment Initiation API the parameter MUST contain the “payments” keyword, for Account/Transaction API the parameter MUST contain the “accounts” keyword, for Confirmation of Funds API the parameter MUST contain the “fundsconfirmations”.
  • response_type - “code id_token”, the response type specified in the OpenId configuration

Additional parameters such as state and nonce will be ignored following FAPI guidelines.

Caution! Whitespaces in the redirect URL should be encoded as %20 and not +

JWT request

See jwt.io for more information in JWT parsing, creation and validation. For a detailed description of request syntax look here. For Danske Bank OpenId flow the following is required

Header

{
  "kid": "S45N1lbPvvbiU0KbbNohrCuL_Kw",
  "alg": "PS256"
}

kid - The Key ID that is present in public JWKS shared during registration that corresponds to the private key used to sign the JWT

Payload

{
  "aud": "https://obp-api.danskebank.com",
  "scope": "openid accounts",
  "claims": {
    "id_token": {
      "acr": {
        "values": ["urn:openbanking:psd2:sca", "urn:openbanking:psd2:ca"],
        "essential": true
      },
      "openbanking_intent_id": {
        "value": "urn:accounts:v3:11111111-2222-3333-4444-555555555555",
        "essential": true
      }
    }
  },
  "iss": "1234567890",
  "nbf": "1588933930",
  "response_type": "code id_token",
  "redirect_uri": "https//tpp.domain.com/callback?optional=parameter",
  "state": "2wB3vfEJBX",
  "exp": 1588934290,
  "nonce": "WH7Uj7l5dN",
  "client_id": "1234567890"
}

Additional info:

  • State parameter will be used in the redirect back to TPP if present.
  • The redirect URL inside the JWT will take precedent over the redirect in the URL. In case the request JWT is missing or can't be decoded the error redirect will use the redirect from the URL.
  • The aud value should correspond with the issuer value of OpenId configuration(iss)
  • TPP client Id should be used for iss and client_id
  • exp claim should have a lifetime of no longer than 60 minutes after the nbf claim
  • nonce is required

Signature

Danske Bank should be able to validate the signature using the KID provided in the header and the JWKS shared during registration or via Open Banking Directory (UK).

[4.1] App-to-App redirection

(from week 35, 2021)

In order to use App-to-App redirection in PSD2 flows, a different domain name should be used:

  • Private PSUs - to open Mobile Bank 3.0 use psd2-mb3.danskebank.com
  • Business PSUs - to open District Mobile use psd2-dm.danskebank.com

Open Banking UK - same domain name as for the default redirect flow, both for private and business PSU’s.

Additional App-to-App references

[5] PSU performs authorization

The PSU is redirected to the authentication screen. The number of available authentication methods depends on the context (country, customer type, sandbox/production). Information about test customers for Sandbox environment can be found in the Test Data section: link. After PSU successfully authenticates he is redirected to the consent screen where he can review the authorizations requested by TPP and agree or decline them.

[6] TPP receives authorization code

Authorization service redirects PSU to TPP. The response will be returned using the redirect_uri parameter, preserving the query parameters and passing the hybrid flow response parameters in the fragment part of the URL

The redirect request may look like this:

https//tpp.domain.com/callback?optional=parameter#code=C****&state=2wB3vfEJBX&id_token=idToken
  • state - the state value sent by the TPP
  • code - authorization code used in the Authorization Code Grant token request. Read more
  • id_token - the JWT signed by Danske Bank, containing the information about the authorized consent (Read more)

It is advised to validate the signature of the id_token, insuring that Danske Bank has indeed authorized the request. The signature can be validated by finding the corresponding KID (public certificate) in the JWKS shared in the OpenId configuration.

Example ID Token Payload:

{
  "iss": "https://obp-api.danskebank.com",
  "iat": 1588074764,
  "exp": 1588075064,
  "sub": "urn:accounts:v3:11111111-2222-3333-4444-555555555555",
  "acr": "urn:openbanking:psd2:sca",
  "openbanking_intent_id": "urn:accounts:v3:11111111-2222-3333-4444-555555555555",
  "aud": "1234567890",
  "c_hash": "ejL1cZ03cEpd3uczB4CKcg",
  "nonce": "WH7Uj7l5dN",
  "s_hash": "hAUtFf-J15547MC3d3_61A"
}

Notable parameters:

  • aud - TPP client ID
  • c_hash - hash of authorization code [ID Token]
  • s_hash - hash of state sent by the TPP [ID Token]
  • nonce - nonce sent by the TPP
  • sub - Consent Id
  • openbanking_intent_id - Consent Id

[7] TPP verifies info from Danske Bank

TPP verifies the received information. TPP verification should include:

  • check if “state” is the same as sent in [4],

  • check if “id_token” is valid:

  • check if jwt’s signature is correct,

    - aud contains valid TPPs client id,

    - openbanking_intent_id, sub contain the account access consent id created in [3],

    - nonce contains the nonce value,

    - c_hash matches the code parameter,

    - s_hash matches the state parameter.

[8] TPP retrieves access token

To get the authorization code access token a request to the token endpoint described in OpenId configuration(token_endpoint)

Example request body:

grant_type=authorization_code&code=C****&redirect_uri=https%2F%2Ftpp.domain.com%2Fcallback%3Foptional%3Dparameter&client_id=1234567890

Sample response might look like this:

{
  "token_type": "Bearer",
  "access_token": "T1****",
  "metadata": "m:consent=urn:accounts:v3:11111111-2222-3333-4444-555555555555&nonce=WH7Uj7l5dN&acr=urn:openbanking:psd2:sca",
  "expires_in": 3600,
  "consented_on": 1588934029,
  "scope": "openid accounts",
  "refresh_token": "R1****",
  "refresh_token_expires_in": 7776000,
  "id_token": "idToken"
}

Parameter description:

  • metadata - additional metadata information about the authorized consent

  • id_token - signed JWT as defined in OpenID Connect. It provides proof for the TPP that PSU authenticated and gave consent to TPPs request.

    - Contains at_hash, which is the hash of access token

  • expires_in - token validity duration, in seconds (1 hour)

  • refresh_token_expires_in - PSU authorization validity period, in seconds (90 days)

  • access_token - token used to request the protected resources, shared by the PSU, valid for 1 hour

  • refresh_token - token used to refresh the access token once it expires, valid for 90 days

Refresh Token Grant

The access token acquired in step [8] has a limited time to live (1h). If you call the API with an expired token you will receive a response similar to this:

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
    "httpCode":"401",
    "httpMessage":"Unauthorized",
    "moreInformation":"application is not registered, or active"
}

Once the Authorization Code Grant access token expires, the TPP can use the refresh token received previously to get new tokens. The same token endpoint described in OpenId configuration is used for that.

Example request body:

grant_type=refresh_token&refresh_token=R1****&scope=openid+accounts&client_id=1234567890

Example response:

{
  "token_type": "Bearer",
  "access_token": "T2****",
  "expires_in": 3600,
  "consented_on": 1588074706,
  "scope": "openid accounts",
  "refresh_token": "R2****",
  "refresh_token_expires_in": 7776000
}

Validations

Danske Bank follows the Open Banking UK security profiles and specifically Financial Grade API (FAPI) Profile. The FAPI Conformance Suite is used to ensure adherence to the standard.