Skip to main content

Integrate from a mobile app

App integrations are currently based on using browsers.

You can enable automatic switch of users back to the merchant app, from the Vipps/MobilePay app.

This flow is designed to be used with apps. It requires that the app initiate Login in an external browser that is opened within the app, as described in Using Login in native applications.

warning

Do not use web views.

The merchant must specify the app URI, where the user will be returned after completing the confirmation in the Vipps/MobilePay app.

Expected flow:

User flows

This flow can be enabled per login request by adding the requested_flow=app_to_app and app_callback_uri parameters to the Authorize request.

This flow requires both the app_callback_uri and redirect_uri parameters.

info

For app URIs, we recommend using universal links (Apple)/asset links (Android) instead of custom URL schemes for better security.

The app_callback_uri should be a URI that makes the device switch back to the merchant's app again after the Vipps/MobilePay app portion of the flow is done (example: "https://example.com/app/callback").

The redirect_uri is opened in the browser once the login flow is completed there. This URI can either redirect the user to a page in the browser, or be handled/intercepted by the merchant app. In either case, it is important to avoid using static client secrets in the app for completing the login. (For more information, see AppAuth for Android Utilizing client secrets (DANGEROUS) and OAuth 2.0 for Native Apps: Client Authentication).

Both URIs must be added to the sales unit from the merchant portal, as described in Portal: How to set up login on your sales unit.

Please note: URIs specified in the merchant portal 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"

The Vipps/MobilePay app will return some data with the return to the app_callback_uri. It contains two query parameters state and resume_uri. State is the OIDC state parameter passed at the start of a login which can be used to identify the specific login if needed.

The resume_uri parameter that we generate can optionally be used to resume the login when the user returns from the Vipps/MobilePay app. If the merchant app manages to keep the initial browser window open it is not required to use the resume_uri. To use the resume_uri, it must be opened in the same browser used in the initial phase (such as ASWebAuthenticationSession or Chrome Custom Tabs). It is required that the browser contains the cookies from the interaction that happens before the user is sent to the Vipps/MobilePay app.

Example app_callback_uri request:

https://example.com/app/callback/?state=RFiQdrl_lvJUpVmTRSKmsZRGLM0G1N1qh0WebZ1gDNk&resume_uri=https%3A%2F%2Fapi.vipps.no%2Fvipps-login-idp%2Findex.html%3FtabId%3D7607f7f0-7ae2-49b7-9cb5-102143dac4ea

A typical flow/implementation might look like this

User flows

The dotted lines in this diagram are handled by us (or the user), while the filled lines need to be implemented by the merchant.

  1. The merchant's backend generates an OpenID authentication flow authorization URI.
  2. The URI is communicated to the merchant's app in the API response.
  3. The merchant's app uses the URI to initiate Login in an external browser that is opened within the app. See the specification for details.
  4. Login will open the Vipps/MobilePay app, if required. (If the user is remembered in the browser, they will be authenticated directly, and they will then be on step 8 below).
  5. The user accepts the login in their Vipps/MobilePay app.
  6. Vipps/MobilePay app opens the deep link app_callback_uri parameter after the user has approved the login.
  7. Merchant app handles the link in one of two ways:
    • Display the same browser instance that was created in (1).
    • Open a browser again using the resume_uri-query parameter that is returned with the request to the app_callback_uri.
  8. The user consents in the browser controlled by the merchant's app.
  9. The redirect_uri is opened, with the code and state. The Login process has now finished, and the merchant controls the remaining process.
  10. Merchant app sends the code and state parameters received in the callback to the merchant backend.
  11. Merchant backend fetches the access token and uses it to fetch /userinfo. (2 separate requests)
  12. Login provides tokens and userinfo. (2 separate responses)
  13. Merchant backend delivers user information to merchant app.

Example authorize request URL:

.../oauth2/auth?app_callback_uri=https://example.com/app-callback&requested_flow=app_to_app&scope=<scopes>&response_type=code&redirect_uri=https://example.com/app-callback&code_challenge_method=S256&state=<state>&nonce=<nonce>&client_id=<clientid>&code_challenge=<challenge>

Parameters state and possibly error will be passed as query parameters to the app_callback_uri. The state parameter has the same value as the state parameter passed to the Authorize request.

Example success callback from app (step 4):

https://example.com/app-callback?state=218gz18yveu1ybajwh2g1h3g&resume_uri=https://.../vipps-login-idp/index.html?tabid=fjeiwfje43t
https://example.com/app/app-callback?state=218gz18yveu1ybajwh2g1h3g&resume_uri=https://.../vipps-login-idp/index.html?tabid=fjeiwfje43t

Example error callback from app (step 4):

https://example.com/app-callback?state=218gz18yveu1ybajwh2g1h3g?error=unknown_error
https://example.com/app/app-callback?state=218gz18yveu1ybajwh2g1h3g?error=unknown_error

Example success callback from browser (step 6):

https://example.com/redirect-uri?state=218gz18yveu1ybajwh2g1h3g&code=<code>&scope=openid
https://example.com/app/redirect-uri?state=218gz18yveu1ybajwh2g1h3g&code=<code>&scope=openid

Help us improve our documentation

Did you find what you were looking for?