Criipto
  1. eIDs
  2. Danish MitID

JWT/Token examples

MitID for citizens

{
"identityscheme": "dkmitid",
Overall eID used to authenticate
"nameidentifier": "0f9960a0d28d4353a3e2ea07f8ffa185",
Legacy format of 'sub'
"sub": "{0f9960a0-d28d-4353-a3e2-ea07f8ffa185}",
Persistent pseudonym. Uniquely identifies an eID user (per Criipto Verify tenant)
"uuid": "74ffcd31-fbaf-4c33-bdac-169f25c1e416",
Danish MitID Person-ID (a persistent pseudonym which the DK authorities can use to identify the person). For citizens, it identifies the natural person. For employees, it identifies the legal person.
"cprNumberIdentifier": "2101270087",
Danish SSN (CPR Nummer)
"birthdate": "1927-01-21",
"age": "93",
"name": "Ditlev Von Testesen",
"country": "DK"
}

MitID for citizens (with address lookup)

Address lookups is available as an add-on for MitID.

{
"identityscheme": "dkmitid",
Overall eID used to authenticate
"sub": "{3687039b-97c3-4c67-aeb6-4da85f7e5818}",
Persistent pseudonym. Uniquely identifies an eID user (per Criipto Verify tenant)
"address": {
"formatted": "Paiman Petersen\nGrusgraven 1,3 tv\n3400 Hillerød\n(Lokalitet ukendt)\nDanmark",
"common_name": "Paiman Petersen",
"street_address": "Grusgraven 1,3 tv",
"postal_code": "3400",
"city": "Hillerød",
"locality": "(Lokalitet ukendt)",
"region": null,
"country": "Danmark"
},
"address_details": {
"road": "Grusgraven",
"road_code": "1732",
"municipality": "Lyngby-Taarbæk",
"municipality_code": "0173",
"house_number": "001",
"floor": "03",
"apartment_code": " tv"
},
"uuid": "8e6ab4ea-58b9-4130-a900-4366ba54eed9",
Danish MitID Person-ID (a persistent pseudonym which the DK authorities can use to identify the person). For citizens, it identifies the natural person. For employees, it identifies the legal person.
"cprNumberIdentifier": "2712589100",
Danish SSN (CPR Nummer)
"birthdate": "1958-12-27",
"age": "63",
"name": "Paiman Petersen",
"country": "DK"
}

Test users

You create personal MitID test users at https://pp.mitid.dk/test-tool/frontend:

  1. Just use the autofill button and then change the details to you liking
  2. If you haven't done so already install the test app from https://pp.mitid.dk/mitid-app/index.html
  3. You can test your new users by using the "Flows" menu at the top of the screen.

MitID test tool

To create MitID Erhverv users, follow these steps.

Collecting CPR numbers

You must enable the "Add CPR for MitID logins" toggle in the management dashboard. Criipto Verify will prompt the user for their CPR number and validate that it belongs to the MitID user that is logging in.

For applications configured to use a static scope strategy, the CPR will be added to the issued token.

For applications configured to use a dynamic scope strategy, supply scope=openid ssn in the authorize request.

Criipto provides users with the option to store their CPR number for 1 year, after which the user must provide explicit CPR consent again.

Criipto stores CPR numbers in encrypted format. The consent is per-tenant only.

You can add a "forget-me" link on your website if you want to let users revoke the consent again. Use a normal authorize request as target, but add a prompt=consent_revoke query parameter to the request. Criipto will then run a login flow (to be able to recognize the end user), and delete the granted consent.

You can learn more about authorize requests in our authorize URL builder.

Collecting user addresses

If you collect the users CPR number, the users current address can also be made available.

Data processor and dedicated billing agreements are needed, contact sales@criipto.com for the legal and financial arrangements.

For applications configured to use a static scope strategy, address data will automatically be added.

For applications configured to use a dynamic scope strategy, supply scope=openid address in the authorize request.

If you do not also request the ssn scope, Criipto Verify will query the user for the CPR number anyway, as this is needed to look up the users address.

The CPR number will not be issued in the JWT in this case, even if the user was prompted for it during login.

Example (partial) authorize request with scope

https://YOUR_SUBDOMAIN.criipto.id/oauth2/authorize?scope=openid address&...

Alternatively, you can send it in the login_hint

https://YOUR_SUBDOMAIN.criipto.id/oauth2/authorize?...&login_hint=scope:address&...

which can be a useful if you are working with technology that does not let you control the scope value.

ReAuthentication

MitID supports a "ReAuthentication" flow where the username input step can be skipped if you know the users uuid ahead of time.

login_hint=uuid:<uuid> to trigger re-authentication when UUID is known.

Controlled Transfer

MitID supports transferring authenticated users from one service provider to another without requiring additional authentication. This is called a Controlled Transfer. Controlled Transfers require that you partner with each service provider that you would like to transfer users to or from, since it is up to the service providers themselves to coordinate the transfer.

It is your responsibility to obtain consent from the end user to transfer the MitID claims (such as their name and CPR number) obtained in the initial authentication to the receiving service provider. All claims present in the original JWT will be transferred to the receiving service provider.

To enable Controlled Transfer for a session, you must provide login_hint=dk:mitid:ct for the initial authentication. This will add two additional claims, mitid:ct:sid and mitid:ct:sid:exp, in the JWT we issue once the user is authenticated.

The mitid:ct:sid claim contains a session token which allows you to initiate Controlled Transfers. You must store this token securely.

The mitid:ct:sid:exp claim contains the time when the session token expires. After this time, it is no longer possible to perform a Controlled Transfer for the session. We suggest that you instead use the ReAuthentication flow to transfer the user if the session token has expired.

To initiate a Controlled Transfer, send a POST request to

https://{YOUR_CRIIPTO_DOMAIN}/DkMitId/ControlledTransfer

containing the following information in JSON format:

{
  "targetBrokerId": "",
  "targetServiceProviderId": "",
  "transferTokenText": "",
  "mitIdControlledTransferSessionId": ""
}
  • targetBrokerId must contain the MitID broker ID of the broker used by the service provider you are sending the user to
  • targetServiceProviderId must contain the MitID service provider ID of the service provider you are sending the user to
  • transferTokenText is a free text field (with a maximum length of 130 characters) that you can use to pass information to the service provider you are sending the user to
  • mitIdControlledTransferSessionId must contain the session token obtained from the mitid:ct:sid claim in the JWT issued when the user first authenticated using MitID

You must obtain both the targetBrokerId and the targetServiceProviderId from your partner service provider. Note that the broker ID and service provider ID will differ between test environments and production. If the targetBrokerId and targetServiceProviderId do not match the service provider attempting to complete the Controlled Transfer, the transfer will fail for security reasons.

The transferTokenText can e.g. be used to send a hash of any additional information you have sent to your partner service provider via other channels to prove that the additional information has not been tampered with. You must coordinate any use of the transferTokenText with your partner service provider.

If the request above is successful, you will receive a JSON response containing a Controlled Transfer Token Exchange Code in the field transferTokenExchangeCode. The Controlled Transfer Token Exchange Code is a one-time token which can be used by your partner service provider to complete the Controlled Transfer in collaboration with their MitID broker. The Controlled Transfer Token Exchange Code must be stored securely. You and your partner service provider must coordinate how you will send them the Controlled Transfer Token Exchange Code.

Criipto currently only supports outbound Controlled Transfers, i.e. sending users from your service to another service. Please contact us if you would like to use inbound Controlled Transfers.

Levels of assurance

MitID via Criipto offers all three levels of assurance via the acr_values urn:grn:authn:dk:mitid:low + urn:grn:authn:dk:mitid:substantial + urn:grn:authn:dk:mitid:high.

If in doubt, our recommendation would generally be to go with Substantial (urn:grn:authn:dk:mitid:substantial).

Read more about eIDAS Levels of Assurance

High

urn:grn:authn:dk:mitid:high allows users to login with username and either of

  • MitID app if it is enrolled with level high
  • Password + MitID Chip
  • MitID app if it is enrolled with level high + MitID Chip

Substantial

urn:grn:authn:dk:mitid:substantial allows users to login with username and either of

  • MitID app
  • MitID code display
  • Any authenticator on level high.

Low

urn:grn:authn:dk:mitid:low allows users to login with username and either of

  • Password
  • Any authenticator on levels high and substantial

MitID for business ('MitID Erhverv')

You can find the details regarding MitID Erhverv here.

Order MitID for production

Prerequisites for ordering

In order to apply for MitID in production on behalf of a company you must meet the basic requirements:

  • Your company must be registered in the EU and have an EU VAT Id.
  • The person applying must be enrolled in MitID Erhverv for your company, or be a signatory of the company.
  • You must have completed step 5 in the Getting ready for production guide. You will need the production domain to complete the order for your client credentials.

MitID went live on October 6, 2021

MitID terms of service

In addition to the general Criipto terms of service you must also accept the MitID specific terms

UX requirements

With MitID you will be using a hosted MitID page at Criipto. The page may be styled to your liking, but some requirements must be observed.

Please see the UX requirements to make sure you comply.

Apply for production access

Companies registered in Denmark

If your company is registered in Denmark please follow these steps:

  1. Go to the management dashboard and set the environment toggle at the top center to "PRODUCTION".
  2. In the "Identity sources" section, expand the "DK MitID" section
  3. A user enrolled in MitID Erhverv must click the button and sign in.
  4. Submit the details for your company. Note the following:
  • The name to show in the MitID login box is the name entered in the "Company alias" box
  1. Press complete when everything is filled out as you like.
  2. Your company will now be created as a Service Provider with Nets, this takes approximately 15-20 minutes, then you can start to use MitID for production logins.

Companies not registered in Denmark

If your company is not registered in Denmark, meaning you don't have MitID Erhverv, please send a request for MitID onboarding to support@criipto.com.

Apply for a custom MitID domain

  1. Go to the "Identity sources" section and open "DK MitID"
  2. At the bottom of the page you will find a button where you can apply for a custom MitID domain
  3. The "Domain prefix" is typically your company or brand name, e.g. acme-corp. Once this registration is completed this will be used to set up your MitID domain, in this case acme-corp.mitid.dk.
  4. The information is sent to Nets who will setup your MitID Domain.
  • Expect this process to take 7-15 work days.
  • Once your domain has been set up, you can complete the onboarding process (read below)

Complete the custom MitID domain process

Once you receive a confirmation from Criipto (via email), go back to the "Identity sources" section and open "DK MitID". Nets has now set up the mitid.dk domain, and the Complete button will be active for you to click.

  1. Click the Complete button in the MitID section to finish the registration process
  2. Configure the various options that appear after the onboarding completes.
    • If you need access to the end-user's CPR number, make sure the Add CPR for MitID logins toggle is enabled.
    • Not all MitID users have a CPR number. If your application can handle the case of a missing CPR, you may enable the CPR Optional toggle. This will let MitID users without a CPR number log in to your service.

Set up an application on your MitID domain

Register your application, just as you would for all other integrations.

Validating token signatures for MitID

MitID comes with a new approach to storing and using token signing keys. There will be a distinct token signing key in use for MitID, in addition to the one you use for other types of eIDs. Criipto Verify announces all of these signing keys in the metadata documents for your domains (see work with metadata for a primer on this subject).

Most modern OIDC libraries have built-in support for dynamic metadata retrieval, so all this should be handled for you behind the scenes.

Dynamic metadata retrieval is also necessary to achieve minimal disruption for your applications in an ordinary key rollover as well as disaster recovery scenarios.

MitID user interface requirements

When supporting MitID in your application, you must adhere to a few style requirements, both in your application and on the MitID landing page hosted by Criipto.

As long as you follow the guidelines below, you should be in compliance with the UX requirements from MitID. However, please reach out to our support if you need assistance verifying that your buttons, pages, and screens comply.

Note that when moving to production with MitID you will be bound by the terms of service for MitID in which you - among other things - commit to the below UX requirements.

Also, Criipto may request that you submit a URL where we can verify that you are, in fact, in line with the requirements.

The MitID landing page

With MitID everything happens on a page hosted by Criipto. Specifically, MitID cannot be iframed, only shown in full page view.

You will therefore redirect the current page to Criipto (alternatively open a browsing component in a native app), or you may open up a popup window. The latter is only relevant on the desktop and is typically not recommended by Criipto.

In the test environment, the MitID landing page will be hosted on a Criipto provided domain: criipto.pp.mitid.dk. In production, you will apply for your own domain.

Styling the landing page

In general, the landing page for MitID may styled by following the general guide on styling. In essence, you can modify the page any way you like using CSS.

As illustrated below, the default landing page has the MitID box - the red rectangle - at the center. It is essential that you do not, under any circumstances, change the styling or layout of anything inside the red rectangle. The required minimum height of the MitID box is 588 pixels, and it is strongly recommended that you always allow the MitID UI elements to fill out the entire viewport width on mobile devices.

It is also required to keep the "Powered by Criipto" text and the links to MitID Support and Privacy Policy - the red rectangle below the MitID box.

MitID default landing page

MitiD branding in your application

When referring to MitID in your application, web or native alike, you must make sure your language and styling matches the requirements.

If you are building a native app a few additional requirements must be observed as described below.

Download the required assets, the MitID logo and fonts, directly from our web site.

Call to Action

When providing a call to action, for example, log in or sign, make sure you follow these requirements:

  • In web applications, always use a button or anchor tag, <a> or <button>, to make sure it is accessible for keyboard navigation and screen readers according to the WCAG 3.0 standard.
  • The button must be the right color of blue with the white text. See the detailed styling below.
  • The button text must be exactly one of the five allowed phrases as listed below.

The MitID button should be shown with lightly rounded corners:

Default MitID Button

The key elements of the default styling are shown below, but we suggest to simply inspect the buttons in the MitID applet and copy the corresponding styles.

{
    background: #0060e6;
    color: #ffffff;
    font-family: "IBM Plex Sans", Helvetica, Arial, sans-serif;
    border-radius: 4px;
    height: 48px;
    padding: .25rem .75rem .25rem 1rem;
}

The text inside the button must be from the set of approved texts:

  Danish  English
Log ind med MitIDLog on with MitID
Godkend med MitIDApprove with MitID
Bekræft med MitIDConfirm with MitID
Acceptér med MitIDAccept with MitID
Underskriv med MitIDSign with MitID

MitID branding in a native app

Just as illustrated above, your app must show a call to action which must open a MitID-compatible browsing component to host the MitID landing page:

MitID CTA in native app

Your app must use a platform-specific, MitID-compatible browsing component which clearly reassures the user that they are on a legitimate mitid.dk domain with appropriate security (TLS and the padlock symbol):

MitID CTA in native app

You can read more about the details of MitID-compatible browsing components here.