Merchant Onboarding API Authentication with OAuth
API Authentication is done through OAUTH2. Partner credentials will be available for the live environment and the playground environment. In case authentication will fail the API responds with HTTP 401 Unauthorized.
Keep in mind that there will be additional credentials associated with a Merchant ID that will be later on used for creating API requests for payments.
Overview
The authenticate towards the Klarna merchant onboarding API works with OAUTH2. First, you need to request an authentication token from the OAUTH2 server that can then be used to execute requests to the onboarding API.
To access the different environments (playground and production) of Klarna, you will have two usernames, one for each environment:
- {{partner_name}} .moma.playground
- {{partner_name}} .moma.production
To request an authentication token for the Klarna onboarding API, you need to create a JSON Web Token (JWT, find further info also here: https://jwt.io/introduction/). This also includes a signature that will be checked by the OAUTH2 server. Therefore, you need an SSH public / private key pair and the public key needs to be added to the Klarna OAUTH2 server.
OAuth2 Authentication
[ Base URL: auth-bp.klarna.com/ ]
For Klarna’s api authorization server. Use /v1/token authorize to get an access_token.
POST /oauth2/v1/token create token
To get an access_token you need to request it by sending a signed JSON Web Token (JWT) with your claims.
Creating a JWT
A JWT is composed of three parts: a header, a claim set, and a signature. The header and claim set are JSON objects. These JSON objects are serialized to UTF-8 bytes, then encoded using the Base64url encoding (! not the standard Base64 encoding; find more details here https://tools.ietf.org/html/rfc4648#section-5). This encoding provides resilience against encoding changes due to repeated encoding operations. The header, claim set, and signature is concatenated together with a period (.) character.
Forming the JWT header
The header consists of two fields that indicate the signing algorithm and the format of the assertion. Both fields are mandatory, and each field has only one value. As additional algorithms and formats are introduced, this header will change accordingly.
The OAuth2 service relies on the RSA SHA-256 algorithm and the JWT token format. As a result, the JSON representation of the header is as follows:
{"alg":"RS256","typ":"JWT"}
Forming the JWT claim set
The JWT claim set contains information about the JWT, including the permissions being requested (scopes), the target of the token, the issuer, the time the token was issued, and the lifetime of the token. Most of the fields are mandatory. Like the JWT header, the JWT claim set is a JSON object and is used in the calculation of the signature.
Required claims
The required claims in the JWT claim set are shown below. They may appear in any order in the claim set.
The JSON representation of the required fields in a JWT claim set is shown below:
{
"iss":"{{partner_name}}.moma.playground",
"scope":"moma.*",
"aud":"https://auth-bp.klarna.com/oauth2/v1/token",
"iat":1510563210,
"exp":1510563810
}
Encoding the JWT claim set
Like the JWT header, the JWT claim set should be serialized to UTF-8 and Base64url-safe encoded.
Computing the signature
JSON Web Signature (JWS) is the specification that guides the mechanics of generating the signature for the JWT. The input for the signature is the byte array of the following content:
{Base64url encoded header}.{Base64url encoded claim set}
The signing algorithm in the JWT header must be used when computing the signature. The only signing algorithm supported by the OAuth 2.0 Authorization Server is RSA using SHA-256 hashing algorithm. This is expressed as RS256 in the alg field in the JWT header.
Sign the UTF-8 representation of the input using SHA256withRSA (also known as RSASSA-PKCS1-V1_5-SIGN with the SHA-256 hash function) with the private key obtained from Klarna. The output will be a byte array.
The signature must then be Base64url encoded. The header, claim set, and signature are concatenated together with a period (.) character. The result is the JWT. It should be the following (line breaks added for clarity):
{Base64url encoded header}.
{Base64url encoded claim set}.
{Base64url encoded signature}
Below is an example of a JWT before Base64url encoding (line breaks added for clarity):
{"alg":"RS256","typ":"JWT"}.
{
"iss":"{{partner_name}}.moma.playground",
"scope":"moma.*",
"aud":"https://auth-bp.klarna.com/oauth2/v1/token",
"iat":1435052936,
"exp":1435052996
}.
[signature bytes]
Making the access token request
After generating the signed JWT, an application can use it to request an access token. This access token request is an HTTPS POST request, and the body is URL encoded. The URL is https://auth-bp.klarna.com/oauth2/v1/token
The following parameters are required in the HTTPS POST request:
grant_type
Use the following string, URL-encoded as necessary: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion
The JWT, including signature.
Below is a raw dump of the HTTPS POST request used in an access token request:
POST /oauth2/v1/token HTTP/1.1
Host: auth-bp.klarna.com
Content-Type: application/x-www-form-urlencoded
_
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3NjEzMjY3OTgwNjktcjVtbGpsbG4xcmQ0bHJiaGc3NWVmZ2lncDM2bTc4ajVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzY29wZSI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2F1dGgvZGV2c3RvcmFnZS5yZWFkb25seSIsImF1ZCI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92My90b2tlbiIsImV4cCI6MTMyODU1NDM4NSwiaWF0IjoxMzI4NTUwNzg1fQ.i0itMbfrt9UBWbXfImxIXlLf02P286_aaW4Xzb4ON95AoHhtRfcM1Hb0lW1uq5J606o7EiPgWLOrT-3OXJyKp_CilfNFBw7R69b6LcP9yIsZ_KW3u6Ez4f4FogrG0DowUPP_5tpFWI65AVgPCKZ7jiM8V_h_sEGIZNzAr6riCm0
Responses
Code 200
The token was created successfully
Example Value
access_token: 03805109a43a4c1b9fc964189a04b4f2
token_type: Bearer
expires_in: 600
scopeData: optional data
Code 403
The request failed. This is either because the request was not built correctly or because the authentication failed. Check the response body for more details
Example Value
{ "code": "invalidJwt", "message": "The given jwt is invalid!", "errors": [ { "code": "invalidJwt", "message": "JWT (claims->{\"iss\":\"issuer-name\",\"scope\":\"scope-name\",\"aud\":\"https://auth-bp.klarna.com/oauth2/v1/token\",\"iat\":1439378628,\"exp\":1439383798}) rejected due to invalid claims. Additional details: [The Expiration Time (exp=NumericDate{1439383798 -> Aug 12, 2015 2:49:58 PM CEST}) claim value cannot be more than 10 minutes in the future relative to the evaluation time NumericDate{1439378646 -> Aug 12, 2015 1:24:06 PM CEST} (even when providing 90 seconds of leeway to account for clock skew).]" } ] }
Using Token for Authentication
The received token can then be used for authentication towards the Klarna merchant onboarding API. Simply include that within the header of an API request:
Authorization: Bearer {received_token}
The token will expire after 10 minutes so you can cache the token and request a new one with steps described above if needed.