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": ...
}
}
The data
property wraps the actual information in every response returned by the Auth-API and has no other purpose.
The state
property holds the current state of the flow.
It can be one of the following:
PROCESSING
- The state isPROCESSING
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 callEXCEPTION
- 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.
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
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.
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.
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 usedtransport_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 bankauthentication
- the consumer has to authenticate against the bankaccount_selection
- the consumer has several bank accounts that could be used for the currentflow
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 authorizedauthorization
- the authorization of a transfernone
- 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"
}
}
}
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.
The content of the form
property is described by the XS2A Form Scheme.
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">
}
}
}
The redirect
property holds information about the redirect.
The URL
property contains the URL to which the consumer has to be redirected to.
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">
}
}
}
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.
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
}
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.
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
}
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.
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
}
The endpoint will respond with a 200 OK
if a corresponding redirect is found:
{
"redirect_url": String,
"auth_url": String,
}
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
}
The endpoint will respond with a 200 OK
if a corresponding flow is found:
{
"auth_url": String,
"redirect_id": String
}
If no corresponding flow is found the endpoint will return 404 NOT FOUND
.