Auth API

The purpose of the Auth API is to handle consumer's state and if needed the input, too. Whenever consumer input is needed the associated XS2A Form can be retrieved over this API and the response to this form is sent to this API as well.

In most cases the Auth API will be accessed by the XS2A App, but in a white label integration the Auth API is called from the TPP/merchant.

The URL for the Auth API is always dependent on a Flow and can therefore be obtained from the auth_url-field in the client_token that is part of the response when starting a Flow.

Optional available headers for Auth API endpoints:

User-Agent: The user agent from the customer
Client-Agent: A service version from your integration

Fetching the current State from the Auth API

The current state can always be retrieved by calling the Auth API endpoint via GET.

GET <decoded(client_token).auth_url> HTTP/1.1
Host: <Host>
curl -X "GET" "<decoded(client_token).auth_url>"

Result of a successful GET-call

{
    "data": {
        "state": Enum<'PROCESSING', 'CONSUMER_INPUT_NEEDED', 'FINISHED', 'ABORTED', 'EXCEPTION'>,
        "next": ?URL,
        "result": ...
    }
}

data Object, always present

The data property wraps the actual information in every response returned by the Auth-API and has no other purpose.

data.state Enum, always present

The state property holds the current state of the flow. It can be one of the following:

  • PROCESSING - The state is PROCESSING when the api processes incoming information or is polling internally for a state change.
  • CONSUMER_INPUT_NEEDED - The flow is waiting for consumer data to be received through the Auth API (e.g. XS2A App).
  • ABORTED - The flow was aborted through a close flow call
  • EXCEPTION - The flow failed with an exception.
  • FINISHED - The flow has finished.

The states ABORTED, EXCEPTION and FINISHED are terminal states, thus apart from requesting the information of the flow through the flow information call the flow cannot be interacted with.

data.next URL, optional

The next property holds a URL which refers to the endpoint that has to be used for the next call as it can change during the course of a flow. When called with GET it returns the latest result. This should also be used for polling if needed. When called with POST it is possible to e.g. send for example a result for an XS2A Form and retrieve a different result afterwards.

The result property

data.result Object, optional

The result property wraps the actual data from the Auth API that contains the step-specific information. The result can have several different structures (as listed below) that are indicated by its type property.

data.result.type Enum, always present

The type property holds the type of the result and can have the following values:

  • bank_search - indicates that the user has to select a bank. For a white label integration it is strongly advised to start a session with a preconfigured bank, instead of implementing the BankSearch.
  • form - indicates that the consumer has to provide information to continue with the flow.
  • redirect - indicates that the user should be redirected to the bank's website to provide information.
  • error - is returned in cases where the session towards the bank is unrecoverably broken.

data.result.context Enum, always present

The context property describes the current state of the flow. The field can be used to update a GUI in order to display more information to the consumer. Possible values for context are:

  • bank_selection - the consumer needs to select the bank to be used
  • transport_selection - there is a possibility that a consumer has to choose a different bank-account-access-method (e.g. business portal vs private portal)
  • authentication_method_selection - the consumer needs to choose one of the available authentication methods that is available at this specific bank
  • authentication - the consumer has to authenticate against the bank
  • account_selection - the consumer has several bank accounts that could be used for the current flow so the consumer is asked to select one of the possible accounts (only if no account is configured in flow-creation)
  • authorization_method_selection - the consumer has to select on his/her available authorization methods before a transfer can be authorized
  • authorization - the authorization of a transfer
  • none - the current context is either not determinable, or is irrelevant

Response structure if result.type is bank_search

{
    "data": {
        "state": "CONSUMER_INPUT_NEEDED",
        "next": String,
        "result": {
            "type": "bank_search",
            "configuration": {
                "allowed_countries": Array<String>,
                "preselected_country": String
            },
            "context": "bank_selection"
        }
    }
}

data.result.configuration Object, always present

The configuration property is only set if type is bank_search and is only relevant if a bank search is used.

Response structure if result.type is form

{
    "data": {
        "state": "PROCESSING | CONSUMER_INPUT_NEEDED",
        "next": String,
        "result": {
            "type":  "form",
            "form": XS2AForm,
            "key": String,
            "context": Enum< "transport_selection", "authentication_method_selection", "authentication", "account_selection", "authorization_method_selection", "authorization", "none">
        }
    }
}

The response of the type form is the payload that is present in most cases.

data.result.form XS2AForm, always present

The content of the form property is described by the XS2A Form Scheme.

data.result.key String, always present

The key property contains the key needed to encrypt the response to an XS2A Form. The specifics are described in Encryption.

Response structure if result.type is redirect

{
    "data": {
        "state": "CONSUMER_INPUT_NEEDED",
        "next": URL,
        "result": {
            "type":  "redirect",
            "redirect": {
                "url": URL,
                "id": String
            },
            "context": Enum< "authentication", "authorization">
        }
    }
}

data.result.redirect Object, always present

The redirect property holds information about the redirect.

data.result.redirect.url URL, always present

The URL property contains the URL to which the consumer has to be redirected to.

data.result.redirect.id String, always present

The id property is used to identify a redirect in case multiple subsequent redirects to the same URL are required.

Response structure if result.type is error

{
    "data": {
        "state": "EXCEPTION",
        "next": URL,
        "result": {
            "type": "error",
            "category": String,
            "message": String,
            "context": Enum<"bank_selection", "transport_selection", "authentication_method_selection", "authentication", "account_selection", "authorization_method_selection", "authorization", "none">
        }
    }
}

data.result.category String, always present

The category property indicates the top level error-type by showing which party has caught the error. The errors can be found in the Error handling documentation.

data.result.message String, always present

The message is a human-readable explanation of the error.

Example Response for a successful GET-call

{
    "data": {
        "state": "CONSUMER_INPUT_NEEDED",
        "next": "https://authapi.openbanking.klarna.com/xs2a/v1/wizard/1234567890123456789",
        "result": {
            "type": "form",
            "form": {
                "version": "1.0.0",
                "form_identifier": "9a11b19e-077e-4715-904a-a9a2cc891837",
                "elements": [
                    {
                        "type": "input",
                        "key": "USERNAME",
                        "tags": [],
                        "version": "1.0.0",
                        "password": false,
                        "label": "Username",
                        "placeholder": "",
                        "prefill_value": "",
                        "read_only": false,
                        "validator": {
                            "min_length": 0,
                            "max_length": 20,
                            "required": true
                        }
                    },
                    {
                        "type": "input",
                        "key": "PASSWORD",
                        "tags": [],
                        "version": "1.0.0",
                        "password": true,
                        "label": "Password",
                        "placeholder": "",
                        "prefill_value": "",
                        "read_only": false,
                        "validator": {
                            "min_length": 6,
                            "required": true
                        }
                    }
                ]
            },
            "key": "eyJhbGciOiJSUzI1NiJ9.eyJtb2R1bHVzIjoiZDEwOTA3YzBkZjc4ZmI5ZDMyNmI1NzkyZGExZDg2OGRkNGViZWRiMmM1ODI4M2UxNTQ2NzFmMmZhNWY2OThiYTI3NWJjZGE0YjA4YTMwOTM4MWNiYWRlOGVmMzRhMTJkM2RhOTM3YjlmMjI4N2EyYTZjY2YxYWU4YWI3ZGRhZTM3ZWNmNzRkM2JlYWQ1OTdhNmY0ZjkwNWZiMzczNGIxY2FhOTk0ZDlhMmNmYjZiZjUyYzAwNmU2MDNmN2E1NGFlODM0NmZiY2VhZmQzODQwMjRlOWI4ZjkyOWI3ODNiMDc0MTljZGNlNGZkMmJlYTcxMzNhYjk3N2M2OWQ1NjVhNzZjMGU4MWZiMDk0NGM3N2NkMGJjYmU4ZmQ4YzY5MmQ3MDNlMDY0ZGYwNzE0OGUxMDRlOWU3ZGY1NDgxZjIwMmRkMjBiODk5ZTEwM2FlYTZiMjM1YjkyZDc4Y2I3MGMyNTNjMjE0NzcyNWVhYmVhMWU4NDZlM2YwZDgzNmYzODZiNzc3YmMwNmYyZWQzZjVmNzllMzA1YjIzM2I3OWQ1OGI3OWVkYjUxOTU5ZGJmYjk4MjM0YmE1MDE3MWVjM2ZlZWMxOTU4Mjc2NDg1NzEyZjI3MDk1ZGNlZDQ4NDVlYjgyMzg4YWVlMmFjOWRlMDc2YzNiMjE1YzY3OTNjMDNmODkiLCJleHBvbmVudCI6IjEwMDAxIn0.zEfK3O9geI1h4l2SaxxUnbfR3pKy0a5CUs3Bfwxgmd56JCOIIMX-l7KhefELqAALekUwFXT0RnMFWmD4DY99p1gT3ETNeZEe_Spv1ednlrVpaMOi68-FT91l3tyoo-XzycCNeTJ1aGqrttZbuMzAOqLfMnwqd0PszzN7pPEDbwEoatWpX5UpTpYQNNDigZHZOHERqaYEP2Kq0YyZUBYxqPPr_Tvm6qGB4iRB6UG3DxIdCoHV_M3fmuHCP62qI9mHArLP96CC4PcAlGnqLUkRQyWgw5Kdfqj0j5LSNq4CHYlva_KcQAFjGYyBd0GwRUrFZPE6VUWda9Lt4dk0AVY1Pw",
            "context": "authentication"
        }
    }
}

Responding to the Auth API

When the Auth API requires a information from the consumer, e.g. through a form, a redirect or the bank_search, the response needs to be sent to the Auth API as well. The POST request needs to be made towards the URL provided in the data.next property of the response of the previous GET request towards the Auth API.

POST <data.next> HTTP/1.1
Host: <Host>
curl -X "POST" "<data.next>"

The payload of this POST request depends on the type of the response in the previous call. The response to all of these requests is the same as the one provided in the above section "Fetching the current State from the Auth API". Don't forget to add the keys object described in White label Integration.

Responding to bank_search

If a bank_search is submitted the request payload is expected to have the following JSON structure:

{
    "bank_code": String,
    "country_code": String
}

bank_code String, required

The bank_code property has to hold the bank code of the selected bank.

country_code String(2), required

The country_code property has to hold the country code of the selected bank in the ISO 3166-1 alpha-2 representation, e.g. DE, GB, SE.

Responding to form

If a form is submitted the request payload is expected to have the following JSON structure:

{
    "ct": String,
    "iv": String,
    "ek": String
}

It holds the encrypted data of the form response. This additional encryption only has to be done when responding to a form.

The payload of the encrypted data has to be structured as follows:

{
    "form_identifier": String,
    "data": Array<{
        "key": String,
        "value": any
    }>
}

The root element has to have two properties.

form_identifier String, required

The form_identifier is provided in the root element of the form.

data Object[], required

The data property contains the data of the form, which is an array of objects with a key and a value property. This flattened list of key-value pairs does not reflect the possibly nested structure of the initial form data.

These Examples depict several forms and the structure of their corresponding responses.

Responding to redirect

If a redirect is submitted the request payload is expected to have the following JSON structure:

{
    "return_url": URL,
    "redirect_id": String
}

return_url URL, required

The return_url property has to contain the full URL - including all GET-parameters and the hash fragment - to which the consumer was redirected from the bank website.

An example URL might look like this: https://payments.yourwebsite.com/return-from-bank?some-data=12345#more-data

To be able to read the full URL, it might be necessary to fetch it via JavaScript's window.location.href method in the browser, as the hash fragment is usually not passed to the backend via the browser.

redirect_id String, required

The redirect_id property has to hold the id of the redirect that was provided in the response of the previous call.

Retrieving Information about a Redirect

Start redirect from an id

If you want to retrieve information for a redirect from the redirect_id you can use the start endpoint.

POST /xs2a/v1/redirect/start HTTP/1.1
Content-Type: application/json;charset=utf-8
Authorization: Token <token>
Host: <Host>

  <payload>
curl -X "POST" "<Host>/xs2a/v1/redirect/start" \
         -H "Content-Type: application/json;charset=utf-8" \
         -H "Authorization: Token <token>"  \
         -d $'<payload>'

where the <payload> is defined as

{
     "redirect_id": String
}

redirect_id String, required

The id of the redirect to start.

The endpoint will respond with a 200 OK if a corresponding redirect is found:

{
    "redirect_url": String,
    "auth_url": String,
}

redirect_url String, required

The redirect_url to the corresponding redirect.

auth_url String, required

The auth_url to call with the relevant return information (see here).

If no corresponding redirect is found the endpoint will return 404 NOT FOUND.

Resume from an url

If a consumer returns from a redirect there are certain scenarios for which it might be difficult or even impossible to identify the corresponding flow from which the redirect was started. In such cases the resume endpoint could be used to re-identify the corresponding flow from an url.

POST /xs2a/v1/redirect/resume HTTP/1.1
Content-Type: application/json;charset=utf-8
Authorization: Token <token>
Host: <Host>

  <payload>
curl -X "POST" "<Host>/xs2a/v1/redirect/resume" \
         -H "Content-Type: application/json;charset=utf-8" \
         -H "Authorization: Token <token>"  \
         -d $'<payload>'

where the <payload> is defined as

{
     "return_url": String
}

return_url String, required

The url the redirect returned to.

The endpoint will respond with a 200 OK if a corresponding flow is found:

{
    "auth_url": String,
    "redirect_id": String
}

auth_url String, required

The auth_url to call with the relevant return information (see here).

redirect_id String, required

The redirect_id to the corresponding redirect.

If no corresponding flow is found the endpoint will return 404 NOT FOUND.

results matching ""

    No results matching ""