Skip to main content

Integrate from a website

API version: 2.0

Login mostly adheres to the OAuth2 and OpenID Connect standards. The easiest - and strongly recommended - way to integrate with the service is therefore to use a well-renowned OAuth2.0/OpenID Connect Library for your programming language. We don't recommend a specific library, but the Certified OpenID Developer Tools page is a good starting point.

Manual integration

This section contains information necessary to perform a manual integration with Login. This should not be attempted without a solid grasp of the OAuth2 and Open ID Connect standards. All endpoints needed for integration can be found in our OpenID connect discovery endpoint. These endpoints should be fetched dynamically by your application, since they are prone for change.

OpenID connect discovery endpoint

EnvironmentBase URL
Testhttps://apitest.vipps.no/access-management-1.0/access/.well-known/openid-configuration
Productionhttps://api.vipps.no/access-management-1.0/access/.well-known/openid-configuration

The OpenID connect discovery endpoint can be used to retrieve configuration information for OpenID connect clients. We recommend fetching these dynamically, however the response from this endpoint rarely changes. Therefore, it can and should be cached, so it's not fetched over the network on every login. The endpoint responds with a Cache-Control: max-age=3600 header.

You can learn more at the OIDC Standard.

Request

GET:/access-management-1.0/access/.well-known/openid-configuration

Response

Overview

HTTP statusDescription
200 OKRequest successful.
500 Server ErrorAn internal Vipps MobilePay problem.

Example response from the merchant test environment:

{
"issuer": "https://apitest.vipps.no/access-management-1.0/access/",
"authorization_endpoint": "https://apitest.vipps.no/access-management-1.0/access/oauth2/auth",
"token_endpoint": "https://apitest.vipps.no/access-management-1.0/access/oauth2/token",
"jwks_uri": "https://apitest.vipps.no/access-management-1.0/access/.well-known/jwks.json",
"subject_types_supported": [
"public",
"pairwise"
],
"response_types_supported": [
"code",
"code id_token",
"id_token",
"token id_token",
"token",
"token id_token code"
],
"claims_supported": [
"sub"
],
"grant_types_supported": [
"authorization_code",
"implicit",
"client_credentials",
"refresh_token"
],
"response_modes_supported": [
"query",
"fragment"
],
"userinfo_endpoint": "https://apitest.vipps.no/vipps-userinfo-api/userinfo",
"scopes_supported": [
"openid",
"address",
"name",
"email",
"phoneNumber",
"nin",
"birthDate",
],
"token_endpoint_auth_methods_supported": [
"client_secret_post",
"client_secret_basic",
"private_key_jwt",
"none"
],
"userinfo_signing_alg_values_supported": [
"none",
"RS256"
],
"id_token_signing_alg_values_supported": [
"RS256"
],
"request_parameter_supported": true,
"request_uri_parameter_supported": true,
"require_request_uri_registration": true,
"claims_parameter_supported": false,
"revocation_endpoint": "https://apitest.vipps.no/access-management-1.0/access/oauth2/revoke",
"backchannel_logout_supported": false,
"backchannel_logout_session_supported": false,
"frontchannel_logout_supported": false,
"frontchannel_logout_session_supported": false,
"end_session_endpoint": "https://apitest.vipps.no/access-management-1.0/access/oauth2/sessions/logout"
}

OpenID connect discovery URLs

OperationDescriptionEndpoints
OAuth 2.0 AuthorizeStart an OAuth 2.0 authorization.GET:/access-management-1.0/access/oauth2/auth
OAuth 2.0 TokenGet an OAuth 2.0 access token.POST:/access-management-1.0/access/oauth2/token
UserinfoReturns information that the user has consented to share.GET:/vipps-userinfo-api/userinfo
JSON Web Keys DiscoveryGet JSON Web Keys to be used as public keys for verifying OpenID Connect ID Tokens.GET:/.well-known/jwks.json

OAuth 2.0 Authorize

The authorize endpoint is a standard OIDC endpoint used for starting an authorization. The client creates a request URI and directs the resource owner to the constructed URI.

Request

The client constructs the request URI by adding the following parameters to the query component of the authorization endpoint URI using the application/x-www-form-urlencoded format. The client directs the resource owner to the constructed URI using an HTTP redirection response, or by other means available to it via the user-agent.

QueryDescription
response_typeValue MUST be set to "code".
client_idThe client identifier, issued by Vipps MobilePay.
redirect_uriRedirect URI which the user agent is redirected to after finishing a login. Recommend to use universal links (Apple)/Asset links (Android), such as https://example.com/app/callback. If the URI is using a custom URL scheme, a path is required: myapp://path-to-something. See API endpoints required from the merchant.
scopeScope of the access request, space-separated list.
stateAn opaque value (e.g. a GUID) used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. It must be at least 8 characters long to ensure sufficient entropy. In case of a too short state parameter the end-user will be redirected back to the merchant's site with an error.
requested_flowOptional. Request a specific flow for the user. See App integration and Automatic return from Vipps or MobilePay app
market Optional. Supported values: NO, DK, FI, SE. The market where the Login integration is being used. This will be used to help determine if the Login client should be shown in a Vipps or MobilePay theme.
app_callback_uriOptional. The target URI for automatic switch back to merchant app. Requires requested_flow=app_to_app. Example https//example.com/app/callback
final_redirect_is_appOptional. Either true or false. If this is true we will enable some compatibility features to make sure the user is returned to the app.
code_challenge_methodOptional. Used for PKCE, either S256 or plain. Default value is plain
code_challengeOptional. Used for PKCE. The value must be calculated based on the code_verifier later used towards the token endpoint

For example, the client directs the user-agent to make the following HTTP request:

GET:/access-management-1.0/access/oauth2/auth?client_id={client_id}&response_type=code&scope={scopes}&state={state}&redirect_uri={redirect_uri}

You can test this by entering the URL into any browser. This will initiate the log in sequence.

For more information about testing this with the Postman collection, see the step-by-step instructions in the Login Postman guide.

Please note: URIs specified on portal.vippsmobilepay.com must be exactly the same as used in the API calls. Be extra careful with trailing / and URL-encoded entities. If the URIs are not identical you will get this error:

The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client

Response

If the resource owner grants the access request, the authorization server issues an authorization code and delivers it to the client by adding the following parameters to the query component of the redirection URI using the application/x-www-form-urlencoded format.

QueryDescription
codeThe authorization code generated by the authorization server. This code should be sent with the subsequent /token request. The client MUST NOT use the authorization code more than once. The authorization code is bound to the client identifier and redirect URI.
stateThe exact value received from the client during the authorization request.
scopeThe scopes that the end user has consented to. This list will always be the same as in the request query as end users are not allowed to remove individual scopes when they give consent.

For example, the authorization server redirects the user-agent by sending the following HTTP response:

HTTP/1.1 302 Found
Location: https://example.com/callback?code={code}&state={state}&scope={scopes}

If the resource owner declines the access request, or an error occurs, the authorization server adds the following parameters to the query component of the redirection URI using the application/x-www-form-urlencoded format. More details in Error handling

For more general information see the standard specifications OpenID Connect Core 1.0 and RFC-6749 section 4.1.1-4.1.2.

OAuth 2.0 Token

The token endpoint is a standard OIDC endpoint used for requesting Access and ID Tokens. The client constructs the request by adding the parameters described below to the HTTP body by using the application/x-www-form-urlencoded format.

Request

Headers

HeaderDescription
Content-Typeapplication/x-www-form-urlencoded
AuthorizationBasic {Client Credentials}

The Client Credentials is a base 64 encoded string consisting of the client_id and secret issued by Vipps MobilePay joined by :.

Example in JavaScript:

var client_id = 123456-test-4a3d-a47c-412136fd0871
var client_secret = testdzlJbUZaM1lqODlnUUtrUHI=

var wordArrayAzp = CryptoJS.enc.Utf8.parse(client_id + ":" + client_secret);
var client_credentials = CryptoJS.enc.Base64.stringify(wordArrayAzp);

Form content

KeyDescription
grant_typeValue MUST be authorization_code.
codeThe authorization code received as a query parameter on the redirect_uri from the authorization server.
redirect_uriRedirect URI which the user agent is redirected to after finishing a login. Recommend to use universal links (Apple)/Asset links (Android), such as https://example.com/app/callback. If the URI is using a custom URL scheme, a path is required: myapp://path-to-something. See API endpoints required from the merchant. This field is required for OIDC flows, i.e. regular Vipps MobilePay logins.

POST:/access-management-1.0/access/oauth2/token

Response

HTTP statusDescription
200 OKRequest successful.
401 UnauthorizedInvalid credentials.
500 Server ErrorAn internal Vipps MobilePay problem.

Example response:

{
"access_token": "hel39XaKjGH5tkCvIENGPNbsSHz1DLKluOat4qP-A4.WyV61hCK1E2snVs1aOvjOWZOXOayZad0K-Qfo3lLzus",
"id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6InB1YmxpYzo4MGYzYzM0YS05Nzc5LTRlMWUtYjY0NS0xMTdmM2I3NzFhZjgiLCJ0eXAiOiJKV1QifQ.eyJhdF9oYXNoIjoidHlGbkgyMFRPbVBaa2dKVThlNWlLdyIsImF1ZCI6WyJ2aXBwcy1pbnRlZ3JhdGlvbiJdLCJhdXRoX3RpbWUiOjE1NTczMTkyOTYsImV4cCI6MTU1NzMyMjkzOCwiaWF0IjoxNTU3MzE5MzM4LCJpc3MiOiJodHRwczovL2FwaXRlc3QudmlwcHMubm8vYWNjZXNzLW1hbmFnZW1lbnQtMS4wL2FjY2Vzcy8iLCJqdGkiOiI2MmE4NWU1Ni0zZDQ1LTRjN2UtYTA1NS00NjkzMjA5MzI1N2EiLCJub25jZSI6IiIsInJhdCI6MTU1NzMxOTI1NSwic3ViIjoiYzA2YzRhZmUtZDllMS00YzVkLTkzOWEtMTc3ZDc1MmEwOTQ0In0.OljG0W_TCfxkrRntj_5He3U0PH94SDZvlK-dvUJe8H5jj8QSiSnqiv65kyzxdr8Bq1MwG7a6Mtlnn4MoL8AyxKUVe6s81CNaYmwaHsWLw2Z2JmiPn5_X4lEy1nHVDX3R7lFKDQqFLSGnGNPU9bACj-Si18LBR-qv060wEj3b1ShrVeUIZCL1Yhxb6cIGl_8RivRto9dBrzggyOlVTtmoPrm9TLYF7UGWjlbmHTqpBWsCQIOeQqgs7RmSBt5k3O9nmP7guVxo5MWv_2Z0XuCqobLDDXJ29Rk_W6d79y-lPzq_TedNb_lCdVJF7u9qDYFbIPuQwXp26CeIJcR-nc-t0qEoNmLru_x-9Z8dCjjzkZbWqyNsNedQU1zt0WFbHjRkodVoHNcRZVT5W5hCe54lmZ6lUqyKwHW0_3Rpd2CI6lPdCOhC-Tze5cUDfb8jT_0OZqCI_wAuWvb6_4VeHqhvUav6Mh6d7AxNJQYG6BAJo9TzyrG7ho4mSpb2wWMr8gmRi8pTQbqa40whPqptpiz_j4AHcsrRckjYONU0USKlnNcBGc24M4sprcLZ6vxFqDYmDoZwUDRdZWRpUbqm_nCmCKb20Z6l5O7h32KvOApopJe2NIeAynli3Nl05QVGOdoT1mZDLYXbtyb0b_4qhRflySr6gaczcf2ovUKAToKNs_4",
"expires_in": 3599,
"scope": "openid",
"token_type": "bearer"
}

Userinfo

note

This is sometimes referred to as Profile sharing.

The GET:/vipps-userinfo-api/userinfo endpoint returns the payload with the information that the user has consented to share, which is provided in the OAuth 2.0 access token.

You can learn more at OIDC Standard.

Request

Headers

HeaderDescription
AuthorizationBearer {Access Token}

The access token is received on a successful request to the token endpoint.

GET:/vipps-userinfo-api/userinfo

Response

Overview

HTTP statusDescription
200 OKRequest successful.
401 UnauthorizedInvalid credentials.
500 Server ErrorAn internal Vipps MobilePay problem.

Standard example response:

{
"sub": "c06c4afe-d9e1-4c5d-939a-177d752a0944",
"birthdate": "1815-12-10",
"email": "user@example.com",
"email_verified": true,
"nin": "10121550047",
"name": "Ada Lovelace",
"given_name": "Ada",
"family_name": "Lovelace",
"sid": "7d78a726-af92-499e-b857-de263ef9a969",
"phone_number": "4712345678",
"address": {
"street_address": "Suburbia 23",
"postal_code": "2101",
"region": "OSLO",
"country": "NO",
"formatted": "Suburbia 23\\n2101 OSLO\\nNO",
"address_type": "home"
},
"other_addresses": [
{
"street_address": "Fancy Office Street 2",
"postal_code": "0218",
"region": "OSLO",
"country": "NO",
"formatted": "Fancy Office Street 2\\n0218 OSLO\\nNO",
"address_type": "work"
},
{
"street_address": "Summer House Lane 14",
"postal_code": "1452",
"region": "OSLO",
"country": "NO",
"formatted": "Summer House Lane 14\\n1452 OSLO\\nNO",
"address_type": "other"
}
]
}

Example response with marketing consents

{
"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",
"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"
} ]
}
}

JSON Web Keys Discovery

This endpoint returns JSON Web Keys to be used as public keys for verifying OpenID Connect ID Tokens.

Request

GET:/access-management-1.0/access/.well-known/jwks.json

Response

Overview

HTTP statusDescription
200 OKRequest successful.
500 Server ErrorAn internal Vipps MobilePay problem.

Examples: 200 response

{
"keys": [
{
"use": "sig",
"kty": "RSA",
"kid": "public:80f3c34a-9779-4e1e-b645-117f3b771af8",
"alg": "RS256",
"n": "n4kytA_ZeI3Znl96b-zteWmrSHjRmXnvLmACQ4W_BVRTtuhumuoLpOpavUcEOhajbLKqBrANC0dd7ABtL92gHRoVRp8VMSNBG6ykuD04gevxqgm2Gz1mGineWBrjINwY-WboPMqgyZLLKw-JjZ6EqHm67TnWxrKjk3135tGILWvrTJ6ykglGpfH0jpGtEOS6VUuSWeW5VitEGeOFDwWja4mYXZbfGICtKnD6LZOM8sFKyC9diBmDXuXZvxdwdBfVh9JvWMaZ5bJ_mv4iJ0qU0FM1yginRMLXY3MOxwLSLSQjmDPV8NZecUsK-UEfpJl7lvLdEFqKCdqQxkEEyLPMq_rM50F5QIbKa0BYoa973-OR9cJ-XQkLNCtF5i003Z3V-5c7N3xBNlpGYsp4CCvv--zFpxvRZ0k-axgu1Loj1eOZRuX1DL86iTQ6YXcBGPYlRkRNJOn7mkRV8wn8kp_DMlzJ7bgE-NFEA32wFrEimPCrGUfdNdjn6gMsWKcbiHiM4NlIDrCNPiD2CVPrHGuVex8R0cpKU0Cvxc8mXqvDc-VJbrqrRNPbZJh0Zoz4wfK9LESdYGAah9PhgHg5LDFHmhT0W3FPmy1Gmfk2ino4PryJ_rDXe0WT84IEGV9YEM631gDerS63D1dKvTP01YT5sd2Ymn9eptH9grvFeOhuvz0",
"e": "AQAB"
}
]
}

This operation does not require authentication.

API endpoints required from the merchant

The following endpoints are to be implemented by merchants, in order for us to redirect the resource owner to them.

Receive authentication result

After a successful authentication, the user agent is redirected to this endpoint with the following parameters added to the query component. This URI must be pre-registered with us, and it must be supplied as a query parameter on calls to the OAuth2 authorize endpoint.

ParameterDescription
codeThe authorization code generated by the authorization server. The client MUST NOT use the authorization code more than once. The authorization code is bound to the client identifier and redirection URI.
stateThe exact value received from the client during the authorization request.

Example:

HTTP/1.1 302 Found
Location: https://example.com/callback?code={code}&state={state}

Error handling

If the user cancels the login or an error occurs, the user agent is redirected to the authentication result endpoint with the following parameters added to the query component.

ParameterDescription
errorStandard OAuth2 or OIDC error code.
error_descriptionA short text providing additional information on the error that occurred.
stateThe exact value received from the client during the authorization request.

Custom error codes

In addition to the standard errors defined in OAuth2 and OIDC, Login also has some custom error codes that you might see on the redirect:

error_codeDescription
access_deniedUser cancelled the login
server_errorSomething went wrong, please try again
login_requiredUser must log in with interaction
invalid_app_callback_uriThe app callback URI is not on a valid format
app_callback_uri_not_registeredThe app callback URI is not registered as a redirect URI
outdated_app_versionThe user's Vipps or MobilePay app version is too old and needs to be updated
wrong_challengeThe user selected the wrong challenge
unknown_reject_reasonSomething went wrong. Reject reason is unknown.

There may be other errors, so integrators must be able to handle undocumented errors gracefully.

Example:

HTTP/1.1 302 Found
Location: https://example.com/callback?error=access_denied&error_description=user%20cancelled%20the%20login?state={state}

If a fatal error occurs where the user can't be redirected back to the merchant, a generic Vipps or MobilePay styled error page will be shown containing a brief error description.

Call by call

The following is a very basic case, starting with a user clicking Log in with Vipps/MobilePay until the merchant receives login token and the user's information:

  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 authorization_endpoint from .well-known. GET {authorization_endpoint}?client_id={client_id}&response_type=code&scope={scopes}&state={state}&redirect_uri={redirect_uri}

    See Authorization endpoint.

  3. This will bring the user to the Vipps or MobilePay login screen, where they will consent to sharing information with the merchant. After consenting, the browser is redirected to the redirect_uri supplied by the merchant. {redirect_uri}?code={code}&state={state}&scope={scopes}

  4. The merchant uses the code-parameter to obtain the login token. POST {token_endpoint} with code={code}, grant_type=authorization_code, and redirect_uri={redirect_uri} in the application/x-www-form-urlencoded-body. This returns (amongst others) an access_token that can be used to fetch userinfo.

    See Token endpoint.

  5. To obtain userinfo, the merchant must do a GET to the userinfo_endpoint with the header: Authorization: Bearer {access_token}. This returns the information the user consented to sharing.

    See Userinfo.

Browser flow marketing consents

The merchant may choose to include the delegatedConsents scope to collect consents from the user. If the scope is included in the request, the user will be asked to give consents according to merchant specifications. This happens regardless if the user has given consent to share information with the merchant before. This means that this flow is most suitable for registration type flows, not for login flows.

  • Configure the marketing consents.
  • Follow the call by call guide, but with the addition of the delegatedConsents scope in the initial request. This will prompt the user to give consent to the merchant's marketing consents.
  • The userinfo response will contain the user's consent status on the format shown in the Userinfo response example.
  • We recommend collecting marketing consents during the registration flow, rather than the login flow, to minimize how often users encounter the consent screen. To achieve this, consider having two distinct buttons: one for login and one for registration. The registration button should include the delegatedConsents scope, which will trigger the marketing consents screen.

Help us improve our documentation

Did you find what you were looking for?