How it works

App switching

During Strong Customer Authentication, the end-user (PaymentServiceUser, PSU) must authenticate himself/herself using a two-factor approval. The first factor is the user logging in by providing a user name and a password to the authorization endpoint. The second factor is the user’s approval using an Approval App / Code App (mobile application).

This section describes how to enable app-switch in a ThirdPartyProvider (TPP) mobile application. By app-switch is meant:

  • Automatically navigating the End-user to an Approval App / Code App from a TPP mobile application where End-user is attempting to login
  • Navigating back to the TPP mobile application, when the user has approved or cancelled the transaction in the Approval App / Code App

In the TPP mobile application, Strong Customer Authentication (SCA) is started by opening the OAuth request in a Custom Tab (Android) or SFSafariViewController (iOS)

var redirectUri = $"{auth_endpoint}?response_type=code&client_id={yourClientId}&scope={scope}&state={request_state}&code_challenge_method=S256&code_challenge={code_challenge}&redirect_uri={yourRedirectUri}&return_app_url={returnAppUrl}";

The yourRedirectUri should be an App Link (Android) or Universal Link (iOS), which enables sending, e.g. an authorization code, to the TPP App from the Custom Tab / SFSafariViewController, once the end-user has been authenticated and the authorization completes.

The returnAppUrl parameter should be set if Approval App is present on the device and enables return to TPP App from Approval App. The value should be the package name of the TPP App in the case of Android and an urlencoded universal link in the case of iOS.

Once Custom Tab / SFSafariViewController is opened, it will be possible to choose “MitID PSD2 sandbox”. A link will be available to perform app-switch.

Sandbox Approval App

When pressing the link for app-switch in the sandbox environment the following url will be opened:



  • authId is an id of the current authentication.
  • updateUri is the url to request once the user has selected an option (Ok, Cancel, Error).
    The query params ?auth_id={authId}&status=<ok|cancel|error> must be added to updateUri before request is made.

  • returnUri is the url to return to once the update request has been made.

An Approval App for sandbox testing can register for this url scheme.

We have made an Android version of a Sandbox Approval App which can be used as reference. You can either download our APK-file or build your own APK-file based on our sourcecode.
Link to Bankdata public GitHub

Test for Approval App presence on device

Below are some code snippets showing how to check for app presence on a device.


fun deviceHasApprovalApp(): Boolean {
    return try {
        packageManager.getPackageInfo("", 0)
    } catch (e: PackageManager.NameNotFoundException) {

On Android 11+ you may need to add a package query to AndroidManifest.xml


func canOpenApp() -> Bool {
    guard let url = URL(string: “some-approval-app://”) else {
        return false
    Return UIApplication.shared.canOpenUrl(url)

The TPP App must add “some-approval-app” to the plist file using key LSApplicationQueriesSchemes.
After that, it can check for app presence, as shown in the code snippet.

Opening Custom Tab / SFSafariViewConroller from TPP App

Below are some code snippets showing how to open a URL in a Custom Tab / SFSafariViewController:


val customTabsIntent = CustomTabsIntent.Builder().build()
customTabsIntent.launchUrl(MainActivity.this, Uri.parse(redirectUri))


guard let url = URL(string: redirectUri) else {
let safariVC = SFSafariViewController(url: url)
self.navigationController?.pushViewController(safariVC, animated: true)

Enable returning from Approval App to TPP App


An intent filter to the main activity in AndroidManifest.xml is needed to enable Approval App to return to the TPP App:

    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />


The TPP App needs to implement a Universal Link