# Authentication

This page shows the different MitID authentication flows that Signicat supports.

Since the process in all the flows are quite similar, we only provide a step-by-step list with image sliders for the "normal" authentication. The difference lies in the step for the chosen authenticator. The following screen examples show the advanced graphical profile in desktop version.

# Normal authentication

The normal MitID authentication flow consists of two main steps (we assume the user has already selected a login link from the service provider site):

  1. The user enters the username in the MitID Login box.
  2. The user authenticates using authenticators applicable for the requested LoA or AAL.

If you have set up CPR matching, the user is asked to provide their CPR match after step 2. For more details, see CPR matching.

After a successful login, the Approved screen is displayed and the user is redirected to the service provider site as logged in.

This image slider shows an example of a normal authentication with the MitID app authenticator. This example shows the advanced graphical profile in mobile version.

Slideshow slide
Slideshow slide
Slideshow slide
Slideshow slide
Slideshow slide
Slideshow slide
Slideshow slide
Slideshow slide
Slideshow slide
Slideshow slide
Slideshow slide
Slideshow slide

The flow is quite similar when using the other authenticators. The difference lies in the step for the chosen authenticator:

  • MitID app: After having entered the username (no password is needed), the user is asked to approve in the MitID app. The user either approves with a 6-digit PIN or with biometrics (fingerprint or face ID). On desktop it is also possible to approve by scanning a QR code with the MitID app.
  • MitID code display and MitID audio code reader: After having entered the username and password, the user is asked to confirm with a one-time password (OTP) received on their token.
  • MitID chip: After having entered the username and password, the user is asked to confirm with their chip.

The chosen authenticator combination also decides the LoA/AAL (see Possible authenticator combinations).

# CPR matching (add-on)

Signicat offers a CPR match flow that can be conducted after a MitID authentication. This is useful, since private service providers are not permitted to do a direct CPR lookup for a user in MitID, but they can match a given CPR number.

This is an example of Signicat's user interface for CPR matching, displayed after the MitID authentication flow (e.g. see Normal authentication):


This example is in mobile version and with an advanced graphical profile.

MitID enforces a maximum limit of three attempts to match the CPR number within a given authentication.

Signicat supports three possible sources that can provide the CPR number for matching: CPR from user, cache and prefilled subject (see below).

# CPR from user

The end-user provides their CPR number themselves by entering it as an input in Signicat’s CPR user interface (see screen example above). This can be considered the default source for the CPR number: If no other source was provided or the prefilled/cached CPR number does not give a positive match, the user will be prompted to provide it themselves. If the user enters an incorrect CPR number, they are met with a warning as well as information detailing how many remaining attempts they have.

# CPR from cache

If the end-user has provided their CPR number and checked the “Remember my CPR number” checkbox in the CPR user interface (see screen example above) and gets a positive match, Signicat will store the number for that user for a period of 90 days (by default). The next time the user conducts a CPR match flow (within the expiration time period and on the same service) the cached CPR will be used for matching, meaning the user will not have to provide it again themselves.

# CPR from prefilled subject

In the CPR match flow, you can use the subject prefilled parameter to inform Signicat of the CPR number that you want to match against the user being authenticated. The effect of this is that when the user has authenticated, the prefilled subject value will be matched using MitID's CPR matching service. If the match is successful, the transaction will complete without further user action. If the match is unsuccessful, the user will be prompted with the Signicat's CPR user interface (see screen example above) to provide their CPR number manually instead.


The prefilled CPR number is not guaranteed to match the one returned in the result from Signicat. The prefilled CPR number will not be processed by Signicat unless it is passed in an encrypted request (see for example Encrypting authorisation requests). This ensures that the CPR number does not become unencrypted in any URLs that may end up in the end-user's browser history.

See below for OIDC and SAML2 code examples with the subject prefilled parameter.


"login_hint": ["subject-2805542112"]



  <signicat:Prefilled xmlns:signicat="urn:signicat" Parameter="subject">2805542112</signicat:Prefilled>


# Step-up (add-on)

The Step-up flow can be used to reauthenticate a user at a higher LoA or AAL than they were already authenticated at. From the user’s perspective, the difference is that for the Step-up authentication, they do not have to fill in their username and only need to use authenticators that satisfy the new requested LoA/AAL (see Possible authenticator combinations).

If you have the Step-up feature and your method is configured to be used as the basis for a further Step-up authentication, the result will include an auth_token_id claim for OIDC or an auth-token-id attribute for SAML2 (see code examples below). To trigger a step-up based on this authentication, you must prefill the received value in your request. Additionally, you must ensure that the Step-up authentication targets a higher LOA or AAL than the original authentication. This can be done either by prefilling the LOA/AAL or by using a preconfigured method with a higher preconfigured LOA/AAL.

In the following examples, we assume that we have received an Auth Token ID for an authentication at LoA Substantial and we wish to conduct a Step-up at LoA High.


"login_hint": ["authTokenId-mitid:27fbcb32-07d3-4d4b-8db4-e98179f3dfae", "assuranceLevel-HIGH", "assuranceMethod-LOA"]



  <signicat:Prefilled xmlns:signicat="urn:signicat" Parameter="authTokenId">mitid:27fbcb32-07d3-4d4b-8db4-e98179f3dfae</signicat:Prefilled>

  <signicat:Prefilled xmlns:signicat="urn:signicat" Parameter="assuranceLevel">HIGH</signicat:Prefilled>

  <signicat:Prefilled xmlns:signicat="urn:signicat" Parameter="assuranceMethod">LOA</signicat:Prefilled>


# PSD2 (add-on)

Signicat supports using the PSD2 mode in MitID. This ensures that MitID can be used in compliance with the PSD2 RTS (opens new window). Enabling PSD2 mode, restricts the information revealed to the user during a failed multi-factor authentication. For example, a user wants to authenticate using their password, followed by an OTP from their MitID code display. If the user enters the incorrect password and PSD2 mode is enabled, they will not be immediately informed that they entered the incorrect password, as they normally would be. Instead, they will proceed to the MitID code display prompt. Only after completing with the final authenticator, they will be informed that one or more of their authenticators failed, but not which one. The user will then be given the option to restart the authentication process:


The PSD2 feature is available through purchase of the PSD2 Compliance add-on.

# MitID Business (add-on)

This is an add-on to the regular authentication where employees in companies can log in with an identity tied to their employer, e.g. to log into a bank to pay invoices on behalf of a company.

MitID Business should not be confused with the similarly named add-on, MitID Private for Business. MitID Private for Business uses Virk as a lookup source on your private identity, whereas MitID Business uses the NemLog-In Identity Service as a data source and the identity is issued by your company's administrator. The administrator handles and configures the business identities in NemLog-In. If you need more general information, see the MitID Business website (opens new window).

The following diagram shows the differences between MitID Business, MitID Private for Business and MitID Private:


Depending on your business requirements, the MitID Business user can authenticate on behalf of the company in two ways:

  • Use their private MitID credentials
  • Use their dedicated business MitID credentials

If private MitID credentials are used to authenticate, the user’s private MitID identity exists separately from the business identity they select after authenticating.

# MitID Business flow

The flow goes as follows, and applies regardless of whether authentication, authentication-based signing, or signed statement is used.

  1. User authenticates with either their private or dedicated business MitID credentials.
  2. If the authentication flow includes CPR matching, this will occur after authentication.
  3. The user is presented with a selection screen, where they can choose which of their business identities they want to use.

CPR matching

CPR matching will fail if dedicated business credentials were used in step 1, as dedicated business identities have no associated CPR number.


The response will contain the following additional attributes (compared to a normal authentication):

OIDC scope OIDC claim SAML2 attribute Example value
signicat.organization signicat.organization.number mitid.employee.organization.cvr 96413608 Testorganisation mitid.employee.audit.source mitid.employee.audit.source
mitid.employee.audit.timestamp mitid.employee.audit.timestamp 2023-0125T11:05:21.535891Z
mitid.employee.uuid mitid.employee.uuid a878d794-ea8d-4953-9c70-505d0cdcaf3a Erik Hansen
mitid.employee.ial mitid.employee.ial Substantial
mitid.employee.can_represent_organization_alone mitid.employee.can-represent-organization-alone false
mitid.employee.organization.p_number mitid.employee.organization.p-number 1028556051
mitid.employee.organization.cvr mitid.employee.organization.cvr 96413608 Testorganisation nr. 96413608
mitid.employee.rid mitid.employee.rid 79160741

If you want to set up prefilling of the CVR number, it is done in the same way as for Private for Business (see Prefilling a CVR number).

# Set up test users for MitID Business

Testing MitID Business, requires special test users. For more information about how to test MitID for Business, see the NemLog-in guideline for service providers (in Danish) (opens new window).

# MitID Private for Business (add-on)

The "Private for Business" add-on (Privat til Erhverv) allows your users to log in with their private MitID user on behalf of the companies they hold signatory rights in. This login mostly applies to one-person businesses (enkeltmandsvirksomheder).

First, the user is authenticated with MitID, which is used to validate their CPR number. Once the CPR number is validated, Signicat does a lookup towards the Danish Virk (opens new window) to check which companies and organisations the user has signatory rights in. The user is then presented with a view that lets them select which of these entities they wish to represent.

As a service provider, you can control certain aspects of the flow:

  • Whether or not the end-user is allowed to represent themselves.
  • By prefilling a CVR number, the user is required to have signatory rights and is only permitted to log in or sign on behalf of that company (see Prefilling a CVR number).

In the example below, a user has authenticated with MitID and their CPR number has been validated. The user can choose to represent themselves (Helle Jensen) or one of the companies they have signature rights in, e.g. Jensen Services (CVR: 23456789).


If the user then selects to represent Jensen Services, the following attributes will be added to the response:

OIDC scope OIDC claim SAML2 attribute Example value
signicat.organization signicat.organization.number onbehalfof.orgnr 23456789 Jensen Services mitid.employee.audit.source onbehalfof.audit.source
mitid.employee.audit.timestamp onbehalfof.audit.timestamp 2021-0225T09:41:21.535891Z

# Prefilling a CVR number

As a service provider, if you know in advance which company you want the user to represent, you can accomplish this by prefilling the CVR number of that company. The effect of this is that Signicat will verify that the prefilled CVR number matches one of the companies that the user holds signatory rights in and the user will only be allowed to represent that company during their login.

If the prefilled CVR number has no matches, the service provider will receive the following error code (there will be no error displayed in the UI): urn:signicat:error:USER_LACKS_SIGNATORY_RIGHTS_FOR_SPECIFIED_CVR_ERROR

If the user cancels, you will get the standard error code for user cancels: urn:signicat:error:usercancel

You can prefill the CVR number as follows:


"login_hint": ["cvr-23456789"]


  <signicat:Prefilled xmlns:signicat="urn:signicat" Parameter="cvr">23456789</signicat:Prefilled> 

# Session Transfer (add-on)

The MitID Session Transfer feature enables a service provider to securely transfer an authentication to a different service provider, without the user having to re-authenticate.

There are four main parties in a Session Transfer transaction:

  • Initiating service provider ("SP-A").
  • Initiating broker ("Broker-A").
  • Receiving service provider ("SP-B").
  • Receiving broker ("Broker-B").

Using the same broker

The two service providers may be using the same MitID broker, in which case Broker-A and Broker-B represent the same broker during different stages of the flow.

The flow is conducted as follows:

  1. The end-user authenticates with MitID at SP-A.
  2. SP-A initiates a MitID authentication with Broker-A, and the user authenticates successfully.
  3. SP-A must get consent from the user to share the attributes received from the initial authentication with SP-B before proceeding with the controlled transfer.
  4. SP-A requests a Transfer Token Exchange Code from Broker-A, specifying the receiving broker, receiving service provider, and optionally a Transfer Token Text.
  5. SP-A redirects the user to SP-B, and must also provide SP-B with the Transfer Token Exchange Code and Transfer Token Text, if it was specified.
  6. SP-B provides Broker-B with the Transfer Token Exchange Code. The Transfer Token Text must also be provided if it was specified by SP-A.
  7. Broker-B uses the Transfer Token Exchange Code to retrieve the eID attributes from MitID, without the user having to re-authenticate. If SP-A provided a Transfer Token Text in step 4, Broker-B will verify that it matches the one provided by SP-B in step 6.

Warning: Security measure regarding session lifetime

Since MitID has a long lifetime for the Transfer Token Exchange Code, it is important that SP-B completes the Session Transfer immediately upon receiving the Transfer Token Exchange Code (and Transfer Token Text) from SP-A. This is important to mitigate the risk of the Transfer Token Exchange Code being intercepted and used by an attacker to fraudulently authenticate as the end-user.

# OpenAPI documentation

For more details on how to set up the methods, see the OpenAPI documentation for the MitID Session Transfer API:

# Initiating service provider

When using Signicat’s MitID Session Transfer as the initiating service provider, there will be an additional claim/attribute in the response you receive in the initial authentication.

OIDC claim SAML2 attribute Example value Description
signicat.cta_id signicat.cta-id mitid:cta:3d939e76-2bcc-402b-9e81-0770c2f8efd6 Short for “Controlled Transfer of Authentication ID”. Used as a reference to the initial authentication.

The following diagram illustrates the two first steps (see above), where the end-user authenticates with the initiating service provider:


The CTA ID can then be used in a request to Signicat's MitID API. You will need an access token with the client.mitid.cta scope to retrieve the Transfer Token Exchange Code.

The Transfer Token Exchange Code and Transfer Token Text (if provided) must then be passed on to the target (receiving) service provider. The mechanism for how this is done is outside the scope of this documentation, and must be agreed upon between the service providers.

The following diagram illustrates the next steps where the controlled transfer from the initiating service provider to the receiving service provider is performed (see step 3-5 above):


# Receiving service provider

When using Signicat’s MitID Session Transfer as the receiving service provider (SP-B), you can complete the transfer by using the prefilled parameters transferTokenExchangeCode and transferTokenText in your request. Providing transferTokenText is only required if it was specified by the initiating service provider in their request to Signicat's MitID Session Transfer API (see step 4 above).


"login_hint" : ["transferTokenExchangeCode-7ed3cec8-33cb-4852-bc79-ef3293e1dc52", "transferTokenText-Example transfer token text"]


 <signicat:Prefilled xmlns:signicat="urn:signicat" Parameter="transferTokenExchangeCode">7ed3cec8-33cb-4852-bc79-ef3293e1dc52</signicat:Prefilled>
   <signicat:Prefilled xmlns:signicat="urn:signicat" Parameter="transferTokenText">Example transfer token text</signicat:Prefilled> 

The following diagram illustrates the final steps where the controlled transfer is handled in the receiving service provider (see step 6-7 above):


If the authentication is successful, the transaction will complete immediately and you will receive the ID attributes of the end-user.

# App switching: From native mobile app to MitID app

MitID supports the concept of app switching. This means, when the end-user attempts to log into your native app, they are automatically sent to the MitID app for authentication. After they have completed the MitID authentication, they are automatically sent back to your native app. This feature saves the end-user from manually switching between your native app and the MitID app.

For the end-user, the MitID flow with app switching is similar to the steps described in Normal authentication.

Supported WebViews

To perform a MitID authentication from a native app, you MUST display the MitID login flow in Chrome Custom Tabs (Android) or SFSafariViewController (iOS). All other WebViews are not supported by MitID and can break at any time.

The following sequence diagram illustrates the backend communication with the app switching feature:


Description of the steps involved:

  1. Check if the MitID app is installed on this mobile device. See separate section further down.
  2. Make a request to your backend server to create a request URL.
  3. Create a URL to start the MitID authentication. How you create the URL depends on the authentication protocol you are using:
  • OIDC: The URL will be a normal OIDC authentication request URL.
  • SAML2: URL for HTTP redirect binding. For HTTP POST binding, you must handle it a bit differently, by serving a page which POSTs the request to Signicat.
  • Authentication API: The URL returned as authenticationUrl when creating the session in the Authentication API.
  1. The app gets back the URL for starting the authentication.
  2. Open the authentication URL in Chrome Custom Tabs (Android) or SFSafariViewController (iOS). See separate section further down.
  3. The end-user inputs their user ID in MitID's web interface.
  4. The MitID web interface displays a button to launch the MitID app.
  5. The end-user clicks the launch button and the MitID app launches.
  6. The end-user authenticates with PIN or biometrics in the MitID app.
  7. The MitID app automatically triggers a launch of your native app. This is done using an app switch URL which your app reacts to. See separate section further down.
  8. Depending on the platform of your app, you might need to have some handling in the app to bring the already existing Chrome Custom Tabs / SFSafariViewController to the foreground again. It's crucial that the end-user returns to the same view as before the switch to the MitID app occurred. This is because the MitID transaction needs to continue there.
  9. The MitID web interface continues the authentication, possibly asking for the CPR number if you are using this feature.
  10. Upon success, the end-user will be sent back to the result URL according to the authentication protocol you use:
  • OIDC: The user will be sent to the redirect_uri you used when starting the authentication.
  • SAML2: The user will be sent to the AssertionConsumerService URL you used when starting the authentication.
  • Authentication API: The user will be sent to the callback URL you specified when creating the session.
  1. Your backend server must get the authentication result from the authentication protocol and verify the result.
  2. Return the page where you want the end-user to end up after the authentication.

For more details on how to set this up, see the following sub-sections.

# Configuration of app switching

Please supply Signicat a Universal Link to your iOS app, and/or the App Link to your Android app. Signicat will help you set this up in a method for in-app usage. You must call this method for all in-app purposes.

This can be set up in two different ways:

  • Set up one method with redirect URLs for both Android and iOS configured. Then you can control which URL will be used, for example by sending login_hint=platform-ANDROID|IOS for OIDC (or the similar way of sending prefilled parameters for SAML2).
  • Set up two different methods for Android and iOS, with the appropriate mobilePlatform configured.

# MitID app detection

Given the requirement that app switching can only be used when the initiating app is your native app, the options for presenting the MitID Logon page to the end-user is an SFSafariViewController on iOS or a Chrome Custom Tab on Android.


Regardless of which mobile platform is used, your native app must check that the MitID app is installed on the end-user’s device before presenting the MitID Logon page. If the MitID app is not installed, the app switching will not work.

The approach for detecting the presence of the MitID app will depend on the technology used in your native app. The following are examples on how to do this in iOS and Android.

# Android

Code example for checking if the MitID app is installed:

public boolean deviceHasMitIDApp() { 
  try { 
    getPackageManager().getPackageInfo("", 0); 
    return true; 
  } catch (PackageManager.NameNotFoundException e) { 
    return false; 

Starting with Android 11, the following must also be included in AndroidManifest.xml:

<manifest ...>
    <package android:name="" /> 
  <application ... /> 

# iOS

Code example for checking if the production MitID app is installed:

func canOpenMitIDApp() -> Bool {
  guard let url = URL(string: "”) else {
    return false
  return UIApplication.shared.canOpenUrl(url)

In addition, the string mitid-app must be added to the plist with a key of LSApplicationQueriesSchemes.

In pre-production, where the test version of the MitID app is used, you need to use the following URL in the check:

# Starting the authentication in a supported WebView

# Android

Chrome Custom Tabs can be implemented by following Android’s implementation guide at (opens new window). Below is a code snippet for how to open a URL in a Chrome Custom Tab.

CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
CustomTabsIntent customTabsIntent =;
customTabsIntent.launchUrl(MainActivity.this, Uri.parse("AUTH_URL"));

The app must load the MitID authentication in Chrome Custom Tabs, as that’s the only one supported by MitID. Using any other WebView may cause the MitID client to not work as intended.

# iOS

Opening the SFSafariViewController is as simple as instantiating it with a URL and presenting it:

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

The app must load the MitID authentication in SFSafariViewController. Using WKWebView or UIWebView is not supported and app-switch and possibly other functionality will not work properly within these views.

# Returning from MitID app to your native app

In order for the MitID app to return to your app, your app needs to support App Links for Android and Universal Links for iOS.

# Android

Add an intent filter to your main activity in Manifest.xml. Example:

<intent-filter android:autoVerify="true">
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
    android:host="" />

In addition, you need to host an assetlinks.json file on your domain matching the host in the manifest file.

Read more about Android App Links in the developer documentation for Android (opens new window).

# iOS

Your iOS app needs to be set up with a Universal Link. This is done by hosting an apple-app-site-association file on your domain and register a matching domain in the app. Read about Universal Links in the developer documentation for iOS (opens new window).

# 3D Secure (add-on)

MitID with 3D Secure (3DS) support allows you to use MitID in an iframe, and in a cookieless context. The feature is for use in 3DS transactions only.

Here is an example on how it could look in an iframe:

3DS in an iframe click-to-zoom

The following restrictions apply when using MitID with 3DS support:

  • The end-user is limited to the MitID App authenticator. If the end-user does not have a registered MitID App authenticator on their phone or tablet, they can not use MitID with 3DS support.

  • There are some additional requirements for MitID 3DS compared to normal authentication. For further information, contact Signicat at

  • Due to the above limitation, all MitID 3DS authentications will achieve AAL High or AAL Substantial, depending on whether or not the end-user has enrolled their app with App Enhanced Security.

Last updated: 20/09/2023 12:20 UTC