Skip to main content

Merchant initiated login integration

Merchant initiated login is built to support special cases where login does not start in a browser or app.

Merchant initiated login is based on the Client-Initiated Backchannel Authentication (CIBA) standard.

In this flow, the merchant's system triggers the authentication/registration; thus, log-in cannot be done in the user's browser. To ensure a consistent user experience, Merchant initiated login is not allowed on webpages and in apps.

A sales unit can use the Login API for many flows. It is recommended to use the same sales unit for all use cases to ensure that you get the same user ID (sub) on the user across different scenarios.

Login from phone number is initiated using the user's mobile number. This triggers a push message from the user's Vipps or MobilePay app. By clicking the push message, the user is taken to their Vipps or MobilePay app to confirm the authentication/registration. If they haven't already consented to share information with a merchant, such consent will be required. If the user hasn't enabled push from Vipps or MobilePay, they need to manually open the app and possibly pull the home screen down for a refresh to receive the authentication request.

The merchant controls whether the user should get the confirmation of completion in the Vipps or MobilePay app or if they should be taken to the merchant's web page to finalize the flow. For example, the merchant can take the user to their web page to enable input of more information, accept terms and conditions, log the user in at their web page, show relevant information/offers or to continue to set up an agreement or completing a purchase. This is illustrated in How Login works from phone number.

Illustration of how the flow will look when the user ends the flow and gets the confirmation of completion in the Vipps or MobilePay app:

Confirm completion in Vipps or MobilePay app

Illustration of how the flow will look if the user is taken to the merchant's web page:

Redirect to browser

The merchant has the option to show a confirmation code (binding_message) to the user in the app for added security:

Optional confirmation code (binding_message)

Complete login in the Vipps or MobilePay app

Overview

Client-Initiated Backchannel Authentication (CIBA) enables a Client to initiate the authentication of an end-user through out-of-band mechanisms.

  1. The Client shall make an "HTTP POST" request to the Backchannel Authentication Endpoint to ask for end-user authentication.
  2. Login will respond immediately with a unique identifier that identifies that authentication while it tries to authenticate the user in the background.
  3. The Client will receive the ID Token and Access Token by polling the token endpoint to get a response with the tokens.

Call by call

  1. Before all this, the merchant has fetched the OpenID configuration from the well-known endpoint and cached it. See .well-known

  2. The merchant initiates a login by calling the backchannel_authentication_endpoint listed in the OpenID configuration fetched in step 0.

    For details see Authentication Request.

    Example request:

    POST https://api.vipps.no/vipps-login-ciba/api/backchannel/authentication
    Authorization: Basic asdkjhasdjhsad=
    Content-Type: application/x-www-form-urlencoded

    scope=name address openid&login_hint=urn:msisdn:{msisdn}&state=13821s837213bng26e2n61gege26&nonce=21hebdhwqdb7261bd1b23

    Example response:

    200 application/json
    {
    "auth_req_id": "VYGaaAMRkI6SyAm_uIywhxsN2K0",
    "expires_in": 600,
    "interval": 5
    }
  3. The merchant starts polling the token endpoint listed in the OpenID configuration fetched in step 0. See webhook events for an alternative to polling.

    Polling in this context means doing repeated HTTP requests with a delay between them.

    Information about polling. Note that the polling interval should adhere to the interval response parameter (in seconds) returned in step 1.

    For other details about the request, see Token request.

    Example request:

    POST https://api.vipps.no/access-management-1.0/access/oauth2/token
    Authorization: Basic asdkjhasdjhsad=
    Content-Type: application/x-www-form-urlencoded

    grant_type=urn%3Aopenid%3Aparams%3Agrant-type%3Aciba&auth_req_id=VYGaaAMRkI6SyAm_uIywhxsN2K0

    Example pending response (Other possible error responses can be found in the CIBA standard):

    HTTP/1.1 400 Bad Request
    Content-Type: application/json;charset=UTF-8
    {
    "error": "authorization_pending",
    "error_description": "The authorization request is still pending"
    }

    The merchant should keep polling when it receives authorization_pending in the error response. After the user completes the login in the app, the token endpoint will give a successful response similar to the following example:

    HTTP/1.1 200 OK
    Content-Type: application/json;charset=UTF-8
    {
    "access_token": "ciba.W_IfBcSr-askdjhsakjhd",
    "token_type": "Bearer",
    "expires_in": 300,
    "id_token": "eyaksjdhksajhdjkashdjksadjnn91283hedhn.eyasdkjhaskjdhskajhdkjhasdkjhaskjhdwqiuh"
    }
  4. The merchant must do a GET to the userinfo endpoint with the header: Authorization: Bearer {access_token}, using the access_token retrieved in step 2.

    For details see Userinfo request.

    Example request:

    GET https://api.vipps.no/vipps-userinfo-api/userinfo
    Authorization: Bearer ciba.W_IfBcSr-askdjhsakjhd

    Example response:

    HTTP/1.1 200 OK
    {
    "address": {
    "address_type": "home",
    "country": "NO",
    "formatted": "jghj khhjhhkjh\n0603\nOSLO\nNO",
    "postal_code": "0603",
    "region": "OSLO",
    "street_address": "jghj khhjhhkjh"
    },
    "family_name": "Heyerdahl",
    "given_name": "Tor Fos",
    "name": "Tor Fos Heyerdahl",
    "other_addresses": [],
    "sid": "qwieuhwqiuhdiuwqh",
    "sub": "f350ef33-22e2-47d0-9f47-12345667"
    }

Authentication Request

Standard definition: https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#auth_request

The Backchannel Authentication Endpoint is listed as backchannel_authentication_endpoint in the configuration https://api.vipps.no/access-management-1.0/access/.well-known/openid-configuration.

Authentication

The following authentication methods are currently supported:

  • client_secret_basic
  • client_secret_post

The default token endpoint authentication method is client_secret_basic. It is possible to change the authentication method to client_secret_post in the merchant portal. More information in the FAQ.

The login_hint parameter (required)

Supported login hints:

  • Norwegian mobile phone numbers can be targeted by passing login hint as an MSISDN.

    Login hint format: login_hint=urn:msisdn:{msisdn}

    Example: ...&login_hint=urn:msisdn:4712345678&....

  • Customer token. This is supplied in the QR checked in webhook

    Login hint format: login_hint=urn:customer-token:{customerToken}

    Example: ...&login_hint=urn:customer-token:ezakjsedhiuqwhiuhd...

The scope parameter (required)

  • We support the scopes listed at Scopes
  • The legacy nnin scope is not supported, use nin instead.

Example: ...&scope=name address birthDate nin&...

The binding_message parameter (optional)

A human-readable identifier or message intended to be displayed on both the consumption device and the authentication device to interlock them together for the transaction by way of a visual cue for the end-user. It should not be used for attempting to conveying other information.

The requested_expiry parameter (optional)

A positive integer representing the requested expiration time, in seconds, for the authentication. This will set the maximum time the authentication request is valid. The default value typically corresponds to ~10-15 minutes. Minimum is 60 seconds. Maximum is 900 seconds.

Format

The format possible for this field is limited to capital characters 'A-Z', numbers '0-9' and the character '-'. It must also be between 5 and 8 characters long. Regex: ^[A-Z0-9\\-]{5,8}$.

Read more about it in the standard https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html#auth_request.

Example: ....&binding_message=4MZ-CQ3&...

Successful responses

Standard definition: OpenID Connect Client-Initiated Backchannel Authentication Flow: Successful Authentication Request Acknowledgement

Responses according to the standard. Note, we do return an interval parameter which indicates the minimum amount of time in seconds that the Client MUST wait between polling requests to the token endpoint.

Token request

Standard definition: OpenID Connect Client-Initiated Backchannel Authentication Flow: Token Request Using CIBA Grant Type

The responses from this endpoint is according to the standard.

  • Note the required grant_type: urn:openid:params:grant-type:ciba.
  • The access token can be used towards the standard OIDC userinfo endpoint.

Polling

Error responses

In addition to the responses defined by the standard these responses might be returned:

  • 429 status responses: Too many login requests started towards the same user at the same time. Please respect the Retry-After header returned.
  • error_code=old_app: The user's Vipps or MobilePay app is outdated and does not support this login flow.
  • error_code=invalid_user: No account exists, the user's account is not active, or the user is in some way not eligible to use this login flow currently e.g. U15 users.

Redirect to browser

Overview

This CIBA-related flow enables a Client to initiate the authentication of an end-user through out-of-band mechanisms and additionally facilitates the end user to be taken to the client's web page to finalize the flow.

  1. The Client shall make an "HTTP POST" request to the Backchannel Authentication Endpoint to ask for end-user authentication.
  2. The user, via their browser, will be redirected to the Client's redirect_uri which enables the login to be completed.

Call by call

  1. Before all this, the merchant has fetched the OpenID configuration from the well-known endpoint and cached it. See .well-known.

  2. The merchant initiates a login by calling the backchannel_authentication_endpoint listed in the OpenID configuration fetched in step 0.

    For details see Authentication Request With Redirect.

    Example request (the real payload will likely look different because of encoding):

    POST https://api.vipps.no/vipps-login-ciba/api/backchannel/authentication
    Authorization: Basic asdkjhasdjhsad=
    Content-Type: application/x-www-form-urlencoded

    requested_flow=login_to_webpage&scope=openid name address&login_hint=urn:msisdn:{msisdn}&redirect_uri=https://merchantwebpage.com/callback

    Example response, the auth_req_id should be used to connect this login to a token response since the ID token should contain the same auth_req_id value.

    200 application/json
    {
    "auth_req_id": "VYGaaAMRkI6SyAm_uIywhxsN2K0",
    "expires_in": 600,
    "interval": 5
    }
  3. The user confirms the login and is then redirected to the redirect_uri passed in the initial request 1. The redirect will contain a code: {redirect_uri}?code={code}.

  4. The merchant uses the code-parameter to obtain the login token. Perform a POST request towards the {token_endpoint} with code={code}, grant_type=urn:vipps:params:grant-type:ciba-redirect in the application/x-www-form-urlencoded-body. This returns an ID token and an access token that can be used to fetch userinfo. The ID token is a JWS that must be validated, see ID Token. The merchant must validate that it contains the auth_req_id they have previously received from step 2.

    Example request (the real payload will likely look different because of encoding):

    POST https://api.vipps.no/access-management-1.0/access/oauth2/token
    Authorization: Basic sadlksadkjasjdaksd
    Content-Type: application/x-www-form-urlencoded

    code=some-valid-code&grant_type=urn:vipps:params:grant-type:ciba-redirect

    Example response:

    {
    "access_token": "hel39XaKjGH5tkCvIENGPNbsSHz1DLKluOat4qP-A4.WyV61hCK1E2snVs1aOvjOWZOXOayZad0K-Qfo3lLzus",
    "id_token": "eyJraWQiOiJwdWJsaWM6ZWUzNmQzZjUtMzkzNC00MDI5LTkyNmYtNzdmYTY1YmYwYjRiIiwiYWxnIjoiRVMyNTYifQ.eyJhdWQiOiJlZGRkYjMyZi01MDI4LTQzOTctYjBhYi1lOGVjZjIxOGZkYzIiLCJzdWIiOiI1MTY4ZWUwNi04NzFlLTQ2ZTYtOTQxZS0wMTAzYjk1NzA0OGUiLCJhdXRoUmVxSWQiOiI3QnpBWS1TYlZRSjM4Vi1VMEM3WjZrMjNfQ1kiLCJpc3MiOiJodHRwczpcL1wvZWNlNDZlYzQtNmY5Yy00ODliLThmZTUtMTQ2YTg5ZTExNjM1LnRlY2gtMDIubmV0XC9hY2Nlc3MtbWFuYWdlbWVudC0xLjBcL2FjY2Vzc1wvIiwiZXhwIjoxNjQzMTc5ODM3LCJpYXQiOjE2NDMxNzkyMzd9.iFvmdtRQVliAe91dBu_CZDfBD5I7WCbDTiDQxu4sOTApXFPb5EsSuEBEVfK_-14E7xjcfQLSMa6ZO06YvhRHAA",
    "expires_in": 3599,
    "scope": "openid",
    "token_type": "bearer"
    }

    Decoded ID token JWS example:

    Header

    {
    "kid": "public:ee36d3f5-3934-4029-926f-77fa65bf0b4b",
    "alg": "ES256"
    }

    Payload

    {
    "aud": "edddb32f-5028-4397-b0ab-e8ecf218fdc2",
    "sub": "5168ee06-871e-46e6-941e-0103b957048e",
    "auth_req_id": "7BzAY-SbVQJ38V-U0C7Z6k23_CY",
    "iss": "https://ece46ec4-6f9c-489b-8fe5-146a89e11635.tech-02.net/access-management-1.0/access/",
    "exp": 1643179837,
    "iat": 1643179237
    }
  5. The merchant must do a GET to the userinfo endpoint with the header: Authorization: Bearer {access_token}, using the access_token retrieved in step 3.

    For details see Userinfo request.

    Example request:

    GET https://api.vipps.no/vipps-userinfo-api/userinfo
    Authorization: Bearer W_IfBcSr-askdjhsakjhdasdfgg

    Example response:

    HTTP/1.1 200 OK
    {
    "address": {
    "address_type": "home",
    "country": "NO",
    "formatted": "jghj khhjhhkjh\n0603\nOSLO\nNO",
    "postal_code": "0603",
    "region": "OSLO",
    "street_address": "jghj khhjhhkjh"
    },
    "family_name": "Heyerdahl",
    "given_name": "Tor Fos",
    "name": "Tor Fos Heyerdahl",
    "other_addresses": [],
    "sid": "qwieuhwqiuhdiuwqh",
    "sub": "f350ef33-22e2-47d0-9f47-12345667"
    }

Authentication Request With Redirect

The Backchannel Authentication Endpoint is listed as backchannel_authentication_endpoint in the configuration https://api.vipps.no/access-management-1.0/access/.well-known/openid-configuration.

Authentication

Same as authentication request without redirect

Required parameters: requested_flow, login_hint, scope, redirect_uri

The login_hint parameter (required)

Same as authentication request without redirect

The scope parameter (required)

Same as authentication request without redirect

The binding_message parameter (optional)

Same as authentication request without redirect

The redirect_uri parameter (required)

Redirect URL which the user agent is redirected to after finishing a login. Must be https in the production environment.

Example: ...&redirect_uri=https://merchant.com/callback&...

Error responses

Same as authentication request without redirect

Webhook events

You can receive instant notifications about important events, such as a merchant-initiated login. To set up the basic webhook infrastructure, you need to register your webhook URL, as described in the Webhooks API guide. We'll send the real-time notifications about subscription events to the URL you specify.

To avoid frequent polling of the token endpoint, register a webhook to be notified via a login.merchant-initiated.ping.v1 event when a login is completed.

We support up to 25 webhook registrations per sales unit (MSN) for each login event type. For more about these limits, see webhook limits.

Payload

The payload will contain the auth_req_id that identifies the login.

Example

{
"auth_req_id": "qwieuhwqiuhdiuwqh123"
}

Call by call

  1. The merchant subscribes to the login.merchant-initiated.ping.v1 event.
  2. The merchant initiates a login by calling the backchannel_authentication_endpoint
  3. The user confirms the login.
  4. The merchant receives a webhook event with the auth_req_id that identifies the login.
  5. The merchant calls the token endpoint to get the tokens.

Redirect to browser flow is not supported

Although this flow also allows for receiving webhook notifications for logins, it has a limitation. The token endpoint can only be called once, which means the flow effectively is not compatible with webhook events.

Merchant initiated login marketing consents

If you are just starting out, review the Marketing consents section.

Overview

For Client-Initiated Backchannel Authentication (CIBA), it's possible to initiate the authentication of an end-user through out-of-band mechanisms and collect consents on behalf of the merchant.

  1. The Client shall make an "HTTP POST" request to the Backchannel Authentication Endpoint with scope delegatedConsents to ask for end-user authentication and on behalf of the merchant consents.
  2. Login will respond immediately with a unique identifier that identifies that authentication while it tries to authenticate the user in the background, along with collecting consents.
  3. The Client will receive the ID Token and Access Token by polling the token endpoint to get a response with the tokens.
  4. Token can be used by the Client to retrieve information about the user through the userinfo endpoint, this response will also contain the consents that are approved/declined by the user.

Requesting on behalf consents for merchant is also available for Login from phone number with redirect to browser, by adding scope delegatedConsents to the initial request (1).

Call by call

  1. Before all this, the merchant has fetched the OpenID configuration from the well-known endpoint and cached it. See .well-known

  2. The merchant initiates a login by calling the backchannel_authentication_endpoint listed in the OpenID configuration fetched in step 0 with scope delegatedConsents.

    For details see Authentication Request.

    Example request:

    POST https://api.vipps.no/vipps-login-ciba/api/backchannel/authentication
    Authorization: Basic asdkjhasdjhsad=
    Content-Type: application/x-www-form-urlencoded

    scope=name delegatedConsents openid&login_hint=urn:msisdn:{msisdn}&state=13821s837213bng26e2n61gege26&nonce=21hebdhwqdb7261bd1b23

    Example response:

    200 application/json
    {
    "auth_req_id": "VYGaaAMRkI6SyAm_uIywhxsN2K0",
    "expires_in": 600,
    "interval": 5
    }
  3. The merchant starts polling the token endpoint listed in the OpenID configuration fetched in step 0.

    Polling in this context means doing repeated HTTP requests with a delay between them.

    Information about polling. Note that the polling interval should adhere to the interval response parameter (in seconds) returned in step 1.

    For other details about the request, see Token request.

    Example request:

    POST https://api.vipps.no/access-management-1.0/access/oauth2/token
    Authorization: Basic asdkjhasdjhsad=
    Content-Type: application/x-www-form-urlencoded

    grant_type=urn%3Aopenid%3Aparams%3Agrant-type%3Aciba&auth_req_id=VYGaaAMRkI6SyAm_uIywhxsN2K0

    Example pending response (Other possible error responses can be found in the CIBA standard):

    HTTP/1.1 400 Bad Request
    Content-Type: application/json;charset=UTF-8
    {
    "error": "authorization_pending",
    "error_description": "The authorization request is still pending"
    }

    The merchant should keep polling when it receives authorization_pending in the error response. After the user completes the login in the app, the token endpoint will give a successful response similar to the following example:

    HTTP/1.1 200 OK
    Content-Type: application/json;charset=UTF-8
    {
    "access_token": "ciba.W_IfBcSr-askdjhsakjhd",
    "token_type": "Bearer",
    "expires_in": 300,
    "id_token": "eyaksjdhksajhdjkashdjksadjnn91283hedhn.eyasdkjhaskjdhskajhdkjhasdkjhaskjhdwqiuh"
    }
  4. The merchant must do a GET to the userinfo endpoint with the header: Authorization: Bearer {access_token}, using the access_token retrieved in step 2.

    For details see Userinfo request.

    Example request:

    GET https://api.vipps.no/vipps-userinfo-api/userinfo
    Authorization: Bearer ciba.W_IfBcSr-askdjhsakjhd

    Example response:

    HTTP/1.1 200 OK
    {
    "family_name": "Heyerdahl",
    "given_name": "Tor Fos",
    "name": "Tor Fos Heyerdahl",
    "other_addresses": [],
    "sid": "qwieuhwqiuhdiuwqh",
    "sub": "f350ef33-22e2-47d0-9f47-12345667"
    "delegatedConsents" : {
    "language" : "EN",
    "heading" : "Give consent",
    "text" : "oidc-testclient wants to send you relevant offers through their digital channels.",
    " termsDescription" : "By confirming, you accept oidc-testclient's terms of membership. They are responsible for processing the consents. You can withdraw them at any time on their website.",
    "confirmConsentButtonText" : "Confirm",
    "links" : {
    "termsLinkText" : "Read the terms of use.",
    "termsLinkUrl" : "http://vippsmobilepay.com/legal/terms-and-conditions",
    "privacyStatementLinkText" : "Read the privacy policy.",
    "privacyStatementLinkUrl" : "https://vippsmobilepay.com/privacy-notice"
    },
    "timeOfConsent" : "2022-11-23T11:40:13Z",
    "consents" : [ {
    "id" : "email",
    "accepted" : true,
    "required" : true,
    "textDisplayedToUser" : "Receive offers via email"
    }, {
    "id" : "sms",
    "accepted" : true,
    "required" : false,
    "textDisplayedToUser" : "Receive offers via SMS"
    }, {
    "id" : "digital",
    "accepted" : true,
    "required" : false,
    "textDisplayedToUser" : "I would like to receive digital marketing"
    }, {
    "id" : "personal",
    "accepted" : true,
    "required" : false,
    "textDisplayedToUser" : "Get customized offers"
    } ]
    }
    }

Authentication request

Required parameters are listed in Authentication request login from phone number and Authentication request login from phone number with redirect.

Error responses

Error responses are listed in Error responses login from phone number and Error responses login from phone number with redirect.

Successful responses

See: Successful responses for login from phone number

Token request

See: Token request login from phone number

Polling

See: Polling login from phone number

Check if user exists

Example request:

POST https://api.vipps.no/vipps-login-ciba/api/v1/user-exists
Authorization: Basic asdkjhasdjhsad=
Content-Type: application/x-www-form-urlencoded

login_hint=urn:msisdn:{msisdn}

Example response:

{ "exists": true }

Help us improve our documentation

Did you find what you were looking for?