Authentication

Introduction

ITSME® is a trusted identity provider allowing partners to use verified identities for authentication and authorization on web desktop, mobile web and mobile applications.

The objective of this document is to provide all the information needed to integrate the Login service using the OpenID Connect Core 1.0 specifications.

Prerequisites

Signing up your application in ITSME® B2B portal

Before you can integrate your application with ITSME® Login service, you MUST set up a project in the ITSME® B2B portal. From here, you will be able to

  • Define the ITSME® service you want to integrate;
  • If applicable, specify the User claims you want to obtain;
  • Provide your signature and encryption public keys, also known as your JSON Web Key Set (JWKS). More information can be found in our JSON Object Signing and Encryption (JOSE) page;
  • Share the redirection URI that will be used in one of the steps below.

Checking ITSME® OpenID Provider configuration

To simplify implementations and increase flexibility, OpenID Connect allows the use of a Discovery Document, a JSON document containing key-value pairs which provide details about ITSME® configuration, such as the URIs of the

  • Authorization, Token and userInfo Endpoints
  • Supported claims
  • JWKSet URL
  • ...

The Discovery document for ITSME® Login service MAY be retrieved from:

Environment
SANDBOX https://e2emerchant.itsme.be/oidc/.well-known/openid-configuration
PRODUCTION https://merchant.itsme.be/oidc/.well-known/openid-configuration

Consulting OpenID Connect certified libraries

OpenID Connect provides certified libraries, products, and tools which could help you integrating the ITSME® service. More more information, please visit the official webpage: https://openid.net/developers/libraries/.

Integrating Login service

The ITSME® Login service integration is based on the Authorization Code Flow of OpenID Connect 1.0. The Authorization Code Flow goes through the steps as defined in OpenID Connect Core Authorization Code Flow Steps, depicted in the following diagram:

Sequence diagram describing the OpenID flow

  • The User indicates on your end he wishes to authenticate with ITSME®
  • Your web desktop, mobile web or mobile application (aka 'Relying Party' in the OpenID Connect specification) sends a request to ITSME® (aka 'OpenID Provider' in the OpenID Connect specification) to authenticate the User. This request will redirect the User to the ITSME® Front-End. ITSME® then authenticates the User by asking him:
    • to enter his phone number on the ITSME® OpenID web page
    • authorize the release of some information’s to your application
    • to provide his credentials (ITSME® code or fingerprint or FaceID)

    If you are building a mobile web or mobile application, the User don’t need to enter his mobile phone number on the ITSME® OpenID web page, he will be automatically redirected to the ITSME® app via the Universal links or App links mechanism.

  • Once the User has authorized the request and has been authenticated, ITSME® will return an Authorization Code to the Service Provider Front-End, redirecting the user to your mobile or web application.
  • The Service Provider Back-End calls the ITSME® Token Endpoint and exchanges the Authorization Code for an ID Token identifying the User and an Access Token.
  • The Service Provider Back-End MAY request the additional User information from the ITSME® userInfo Endpoint by presenting the Access Token obtained in the previous step.
  • At this stage you are able to confirm the success of the operation and display a success message.

This flow is described in much more detail in the following sections.

Forging an Authentication Request

First, you will forg a HTTPS GET request that MUST be sent to the ITSME® Authorization Endpoint. The ITSME® Authorization Endpoint can be retrieved from the ITSME® Discovery document, using the key “authorization_endpoint”.

The OpenID Connect Core specification defines a number of parameters to integrate in the HTTPS GET query string:

Parameter
client_id
required
This is the client ID you received when registering your project in the ITSME® B2B portal.
response_type
required
This defines the processing flow to be used when forming the response. Because ITSME® uses the Authorization Code Flow as described above, this value MUST be 'code'.
scope
required
The scope parameter allows the application to express the desired scope of the access request. It MUST contain the value 'openid' and 'service:TEST_code', by replacing 'TEST_code' with the code you received when registering your project in the ITSME® B2B portal.
You MAY also specify additional scopes, separated by spaces, to request more information about the User. Depending on your use case, the following additional scopes MAY apply:

profile: will request the claims representing basic profile information.
These are "family_name", "given_name", "gender", "birthdate" and "locale".
email: will request the "email" and "email_verified" claims.
phone: will request the "phone_number" and "phone_number_verified" claims.
address: will request the "street_address", "locality", "postal_code" and "country" claims.

For more information on User attributes or claims, please consult the ID claims section. An HTTP ERROR "not_implemented" will be returned if the required values are not specified. Unrecognised values will be ignored.
redirect_uri
required
This is the URI to which the authentication response should be sent. This MUST exactly match the redirect URI of the specified service defined when registering your project in the ITSME® B2B portal.
request_uri
optional
This parameter enables OpenID Connect parameters to be passed by reference. The 'request_uri' value is a URL using the https scheme referencing a resource containing a Request Object value, which is a JWT containing the request parameters. The URL MUST be shared with us when registering your project in the ITSME® B2B portal. See Using request_uri parameter for more details.

On top of this, OpenID Connect specify that additionnal parameters MAY be added to the Authentication Request as a JWT Payload in the “request_uri” parameter:

Parameter
state
strongly recommended
An opaque value used in the Authentication Request, which will be returned unchanged in the Authorization Code. This parameter SHOULD be used for preventing cross-site request forgery (XRSF). When deciding how to implement this, one suggestion is to use a private key together with some easily verifiable variables, for example, your client ID and a session cookie, to compute a hashed value. This will result in a byte value that will be infeasibility difficult to guess without the private key. After computing such an HMAC, base-64 encode it and pass it to the Authorization Server as "state" parameter. Another suggestion is to hash the current date and time. This requires your application to save the time of transmission in order to verify it or to allow a sliding period of validity.
nonce
strongly recommended
A string value used to associate a session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token. Sufficient entropy MUST be present in the "nonce" values used to prevent attackers from guessing values. See OpenID Connect Core specifications for more information.
login_hint
optional
Can be used to pre-fill the phone number field on the ITSME® OpenID web page for the User, if your application knows ahead of time which User is trying to authenticate.
If provided, this value MUST be a phone number in the format specified for the "phone_number" claim: "+". E.g.: "login_hint=32+123456789".

"login_hint" with invalid syntax will be ignored.
display
optional
ASCII string value that specifies how the Authorization Server displays the authentication and consent User interface pages to the User. MUST be "page" if provided.
Other values will yield an HTTP ERROR "not_implemented".
prompt
optional
Space delimited, case sensitive list of ASCII string values that specifies whether the Authorization Server prompts the User for reauthentication and consent. MUST be "consent" if provided.
ui_locales
optional
User's preferred languages and scripts for the User interface (e.g.: OpenID web page). Supported values are: "fr", "nl", "en" and "de". Any other value will be ignored.
max_age
not supported
Any supplied value will be ignored.
As ITSME® does not maintain a session mechanism, an active authentication is always required.
acr_values
optional
Space-separated string that specifies the acr values that the Authorization Server is being requested to use for processing this Authentication Request, with the values appearing in order of preference. 2 values are supported:

Basic level: let the User to choose either fingerprint usage (if device is compatible) or PIN
"tag:sixdots.be,2016-06:acr_basic"
Advanced level: force the User to use PIN
"tag:sixdots.be,2016-06:acr_advanced"

When multiple values are provided only the most constraining will be used (advanced > basic). If not provided basic level will be used.

More information on security levels and context data can be found in the Appendixes.
claims
optional
This parameter is used to request specific claims. The value is a JSON object listing the requested claims. See User Data for more information.
response_mode
not supported
Any supplied value will be ignored.
id_token_hint
not supported
Any supplied value will be ignored.
claims_locales
not supported
Any supplied value will be ignored.
registration
not supported
Any supplied value will be ignored.

The JWT Payload in the “request_uri” parameter MAY be signed using the JSON Web Signature (JWS). It MAY also be encrypted using JSON Web Encryption (JWE). In this case, it MUST be signed then encrypted, with the result being a Nested JWT, as defined in the JSON Web Token (JWT) section.

The following is a non-normative example of a request that would be sent to the Authorization Server:

Authentication Request:
GET /oidc/authorization HTTP/1.1 &response_type=code &client_id=MY_PARTNER_CODE &scope=openid service:TEST_code profile email &redirect_uri=https://test.itsme.be &request_uri=https://test.itsme.be:443/p/test

Raw Request Object (not signed, not encrypted):
{ "aud": "https://merchant.itsme.be/oidc/authorization", "scope": "openid service:TEST_code profile email", "redirect_uri": "https://test.itsme.be", "response_type":"code", "client_id":"MY_PARTNER_CODE", "acr_values":"tag:sixdots.be,2016-06:acr_advanced", "iss":"MY_PARTNER_CODE", "nonce":"A_VALID_NONCE", "state":"A_VALID_STATE", "claims":{ "userinfo":{ "tag:sixdots.be,2016-06:claim_eid":null, "tag:sixdots.be,2016-06:claim_city_of_birth":null } } }

Capturing an Authorization Code

Capturing a successful Authorization Code

If the User is successfully authenticated and authorizes access to the data requested, ITSME® will return an Authorization Code to your server component. This is achieved by returning an Authentication Response, which is a HTTP 302 redirect request to the “redirect_uri” specified previously in the Authentication Request. The following is a non-normative example of a successful Authentication Response:

HTTP/1.1 302 Found Location: https://client.example.org/cb? code=SplxlOBeZQQYbYS6WxSbIA& state=af0ifjsldkj

The response will contain:

Values
code
always
The "code" parameter holds the Authorization Code which is a string value. The content of Authorization Code is opaque for you. This code has a lifetime of 3 minutes.
state
if requested
The "state" parameter will be returned if you provided a value in the Authentication Request. You should validate that the value returned matches the one supplied in the Authentication Request. The state value can additionally be used to mitigate against XSRF attacks by cryptographically binding the value of this parameter with a browser cookie.
If a wrong/unknown "state" is received, you should take it into account and refuse the related "code" or from a security detection/prevention point of view, monitor if it is a recurring pattern or not.

Handling Authentication Error Response

If the request fails due to a missing, invalid, or mismatching redirection URI, or if the client identifier is missing or invalid, the Authorization Server SHOULD inform the User of the error and MUST NOT automatically redirect him to the invalid redirection URI.

If the User denies the Authentication Request or if the request fails for reasons other than a missing or invalid redirection URI, ITSME® will return an error response to your application. As for a successful response this is achieved by returning a HTTPS 302 redirect request to the redirection_uri specified in the Authentication Request. The error response parameters are the following:

Values
error
always
Error type.
error_description
always
Indicating the nature of the error.
state
if requested
Set to the value defined in the Authorisation Request, if any.

The following is a non-normative example of an error response:

HTTP/1.1 302 Found Location: https://client.example.org/cb? error=invalid_request &error_description=Unsupported%20response_type%20value &state=af0ifjsldkj

The following table describes the various error codes that can be returned in the “error” parameter of the error response:

Error
interaction_required The Authorization Server requires User interaction of some form to proceed
invalid_request_object The "request" parameter contains an invalid Request Object
registration_not_supported This error is returned because ITSME® does not support use of the "registration" parameter

All other HTTPS errors unrelated to OpenID Connect Core will be returned to the User using the appropriate HTTPS status code.

Regardless of the application you are building you should make sure that your redirect URIs support the Universal links and App links mechanism. Functionally, it will allow you to have only one single link that will either open your desktop web application, your mobile app or your mobile site on the User’s device.

Universal links and App links are standard web links (http://mydomain.com) that point to both a web page and a piece of content inside an app. When a Universal Link is opened, the app OS checks to see if any installed app is registered for that domain. If so, the app is launched immediately without ever loading the web page. If not, the web URL is loaded into the webbrowser.

An App link is the Android version of the Universal link.

How do Universal Links work in iOS and Android ? Before Universal Links, the primary mechanism to open up an app when it was installed was by trying to redirect to an app’s URI scheme in the web browser. But there was no way to check if the app was installed or not. This meant that developers would try to call the URI scheme 100% of the time, in the off chance that the app was installed, then fallback gracefully to the App Store or Google Play Store when not by using a timer.

iOS Universal Links and Android App Links were intended to fix this. Instead of opening up the web browser first when a link is clicked, the OS will check if a Universal Link has been registered (a file should be there in the domain which contains the bundle id of the app and the paths the app should open) for the domain associated with the link, then check if the corresponding app is installed. If the app is currently installed, it will be opened. If it’s not, the web browser will open and the HTTPS link will load.

The specifications for the implementation of Universal links and App links can be found in the Appendix.

Exchanging the Authorization Code

Once your server component has received an Authorization Code, your server can exchange it for an Access Token and an ID Token.

You might also read in the OpenID Connect Core specification about the Refresh Token, but we don’t support them (we don’t implement any session mechanism).

Your server makes this exchange by sending an HTTPS POST request to the ITSME® Token Endpoint URI. This URI can be retrieved from the ITSME® Discovery document, using the key “token_endpoint”.

An Authorization Code can only be exchanged once. Attempting to re-exchange a code will generate a bad request response, outlined below in the section Handling token error response.

The request MUST include the following parameters in the POST body:

Parameter
grant_type
required
This MUST be set to "authorization_code"
code
required
The Authorization Code received in response to the Authentication Request
redirect_uri
required
The redirection URI supplied in the original Authentication Request. This is the URL to which you want the User to be redirected after the authorization is complete.
client_assertion
required
To ensure that the request is genuine and that the tokens are not returned to a third party, you will be authenticated when making the Token Request.
The OpenID Connect Core specifications support multiple authentication methods, but ITSME® only supports "private_key_jwt". The JWT MUST be sent as the value of the "client_assertion" parameter.

See the JOSE specifications for more information.
client_assertion_type
required
This MUST be set to "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"

The JWT Payload in the “client_assertion” parameter MUST be signed then encrypted, with the result being a Nested JWT, as defined in the JSON Web Token (JWT) section.

The following is a non-normative example of a request to obtain an ID Token and Access Token:

POST /token HTTP/1.1 Host: server.example.com Content-Type: application/x-www-form-urlencoded ?grant_type=authorization_code &code=i1WsRn1uB1 &redirect_uri=https://test.itsme.be &client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer &client_assertion=PHNhbWxwOl ... ZT

According to the “private_key_jwt” client authentication method, the “client_assertion” contains the following parameters in the JWT Payload:

Parameter
iss
required
The issuer of the "private_key_jwt". This MUST contain the "client_id". This is the client identifier (e.g. : Project ID) you received when registering your project in the ITSME® B2B portal.
sub
required
The subject of the "private_key_jwt". This MUST contain the "client_id". This is the client identifier (e.g. : Project ID) you received when registering your project in the ITSME® B2B portal.
aud
required
Value that identifies the Authorization Server as an intended audience. This MUST be the ITSME® Token Endpoint URL: "https://merchant.itsme.be/oidc/token".
jti
required
The "jti" (JWT ID) claim provides a unique identifier for the JWT. The identifier value MUST be assigned by the you in a manner that ensures that there is a negligible probability that the same value will be accidentally assigned to a different data object; if the application uses multiple issuers, collisions MUST be prevented among values produced by different issuers as well. The "jti" claim can be used to prevent the JWT from being replayed. The "jti" value is a case-sensitive string.
exp
required
The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of the "exp" claim requires that the current date/time MUST be before the expiration date/time listed in the "exp" claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew. Its value MUST be a number containing a NumericDate value (e.g. 1538507868 for Tuesday, March 22, 2011 6:43:00 PM).

Managing Token Response

Extracting a successful Token Response

If the Token Request has been sucessfully validated we will return an HTTP 200 OK response including ID and Access Tokens as in the example below:

HTTP/1.1 200 OK Content-Type: application/json Cache-Control: no-store Pragma: no-cache { "access_token": "SlAV32hkKG", "token_type": "Bearer", "expires_in": 3600, "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5 NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4 XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg" }

The response body will include the following values:

Parameter
access_token
Always
The Access Token which may be used to access the userInfo Endpoint
token_type
Always
Set to "Bearer"
id_token
Always
The ID Token is a JSON Web Token (JWT) that contains User profile information (like the User's name, email, and so forth), represented in the form of claims.
at_hash
not supported
ITSME® does not provide any value for this parameter.
refresh_token
not supported
ITSME® does not provide any value for this parameter as it only maintains short-lived session to enforce re-authentication.

With the following values returned in the “id_token”:

Values
iss
always
Identifier of the issuer of the ID Token.
sub
always
An identifier for the User, unique among all ITSME® accounts and never reused. Use "sub" in the application as the unique-identifier key for the User. It has 32 characters.
aud
always
Audience of the ID Token. This will contain the "client_id". This is the client identifier (e.g. : Project ID) you received when registering your project in the ITSME® B2B portal.
exp
always
Expiration time on or after which the ID Token MUST NOT be accepted for processing.
iat
always
The time the ID Token was issued, represented in Unix time (integer seconds).
auth_time
always
The time the User authentication occurred, represented in Unix time (integer seconds).
nonce
if requested
String value used to associate a session with an ID Token, and to mitigate replay attacks. The value is passed through unmodified from the Authentication Request to the ID Token. Sufficient entropy MUST be present in the "nonce" values used to prevent attackers from guessing values. See the OpenID Connect Core specifications for more information.
acr
if requested
Could be "tag:sixdots.be,2016-06:acr_basic" or "tag:sixdots.be,2016-06:acr_advanced" depending on the value entered in the "acr_values" Authorisation Request parameter. If no value is provided in the "acr_values" parameter, the "acr" will contain "tag:sixdots.be,2016-06:acr_basic".
amr
never
Not applicable
azp
never
Not applicable

However, before being able to store and use the returned values from “id_token”, you will first need to validate it by following the the ID Token validation rules described in the section below.

ID Token validation

You MUST validate the ID Token in the Token Response in the following manner:

  • As the ID Token is a Nested JWT object, you will have to decrypt and verify it using the keys and algorithms that you specified when registering your project in the ITSME® B2B portal. The process of decryption and signature validation is described in section 4.3 of the JOSE specifications.
    If the ID Token is not encrypted, you SHOULD reject it.
  • The Issuer identifier for ITSME® (which is obtained by using the key "issuer" in the ITSME® Discovery document) MUST exactly match the value of the "iss" claim.
  • You MUST validate that the "aud" claim contains your "client_id" value registered in the ITSME® B2B portal. The ID Token MUST be rejected if the ID Token does not list the "client_id" as a valid audience.
  • The current time MUST be before the time represented by the "exp" claim.

If all the above verifications are successful, you can use the subject (“sub”) of the ID Token as the unique identifier of the corresponding User.

Handling token error response

If the Token Request is invalid or unauthorized an HTTP 400 response will be returned as in the example:

HTTP/1.1 400 Bad Request Content-Type: application/json Cache-Control: no-store Pragma: no-cache { "error": "invalid_request" }

The response will contain an error parameter and optionally “error_description” and “error_uri” parameters. The “error_uri” parameter may be used by implementations to specify a human-readable web page with information about the error, used to provide the client developer with additional information about the error.

Obtaining User attributes or claims

Creating the userInfo Request

OpenID Connect Core specifications also allow your application to obtain basic profile information about a specific User in a interoperable way. This is achieved by sending a HTTPS GET request to the ITSME® userInfo Endpoint, passing the Access Token value in the Authorization header using the Bearer authentication scheme. The ITSME® userInfo Endpoint URI can be retrieved from the ITSME® Discovery document, using the key “userinfo_endpoint”.

GET https://merchant.itsme.be/oidc/userinfo HTTP/1.1 Authorization: Bearer ‹access token›

Managing the userInfo Response

The ITSME® userInfo Endpoint will return a HTTP 200 OK response and the User claims in a Nested JWT format. The following is a non-normative example of a UserInfo Response:

HTTP/1.1 200 OK Content-Type: application/json { "sub": "248289761001", "name": "Jane Doe", "given_name": "Jane", "family_name": "Doe", "preferred_username": "j.doe", "email": "[email protected]", "picture": "http://example.com/janedoe/me.jpg" }

For privacy reasons ITSME® may elect to not return values for some requested claims. In that case the claim will be omitted from the JSON object rather than being present with a null or empty string value.

However, before being able to consume the claims from the userInfo response, you will first need to validate it by following the userInfo response validation rules described in the section below.

UserInfo response validation

You MUST validate the userInfo reponse in the following manner:

  • As the userInfo response is a Nested JWT object, you will have to decrypt and verify it using the keys and algorithms that the you specified when registering your project in the ITSME® B2B portal. The process of decryption and signature validation is described in section 4.3 of the JOSE specifications.
    If the userInfo response is not encrypted, the you SHOULD reject it.
  • The "sub" claim will always be included in the response and this should be verified by you to mitigate against token substitution attacks. The "sub" claim in the userInfo response MUST be verified to exactly match the "sub" claim in the "id_token"; if they do not match, the userInfo response values MUST NOT be used.

When an error condition occurs an error response as defined in the OAuth 2.0 Bearer Token Usage specification will be returned.

Capturing claims from the ‘scope’ parameter

On top of the “openid” and “service:TEST_code” values specified in the Authentication Request, you MAY also ask for additional scopes, separated by spaces, to request more information about the User. The following additional scopes MAY apply:

Parameter
profile
optional
It will request the claims representing basic profile information. These are "family_name", "given_name", "gender", "birthdate" and "locale".
email
optional
It will request the "email" and "email_verified" claims.
phone
optional
It will request the "phone_number" and "phone_number_verified" claims.
address
optional
It will request the "street_address", "locality", "postal_code" and "country" claims.

The values returned via the ITSME® userInfo Endpoint are those below:

Values
family_name
if requested
given_name
if requested
gender
if requested
birthdate
if requested
locale
if requested
The language of the User
email
if requested
The User’s email address. This may not be unique and is not suitable for use as a primary key. Provided only if your scope included the string “email”.
email_verified
if requested
“true” if the User’s e-mail address has been verified; otherwise “false”.
phone_number
if requested
phone_number_verified
if requested
street_address
if requested
locality
if requested
postal_code
if requested
country
if requested

Capturing claims from the ‘claims’ parameter

Typically, the values returned via the “scope” parameter only contain claims about the identity of the User. More information about the User MAY be requested by including additional parameters in the “claims” parameter as specified below:

Values
tag:sixdots.be,2016-06:claim_nationality
optional
It will request the "nationality" claim.
tag:sixdots.be,2016-06:claim_city_of_birth
optional
It will request the "place of Birth - city" claim.
tag:sixdots.be,2016-06:claim_eid
optional
It will request the "eid", "issuance_locality", "validity_from", "validity_to", "certificate_validity", "read_date" and "national_number" claims.
tag:sixdots.be,2017-05:claim_device
optional
It will request the "os", "appName", "appRelease", "deviceLabel", "debugEnabled", "deviceID", "osRelease", "manufacturer", "hasSimEnabled", "deviceLockLevel", "smsEnabled", "rooted", "imei", "deviceModel" and "sdkRelease" claims.
tag:sixdots.be,2017-05:claim_transaction_info
optional
It will request the "securityLevel", "bindLevel" and "mcc" claims.
tag:sixdots.be,2017-05:claim_photo
optional
It will request the "e-ID Picture" claim.

The values returned via the ITSME® userInfo Endpoint are those below:

Values
nationality
if requested
place of birth
if requested
eid
if requested
The eID card serial number.
issuance_locality
if requested
The eID card issuance locality.
validity_from
if requested
The eID card validity “from” date.
validity_to
if requested
The eID card validity “to” date.
certificate_validity
if requested
The eID card certificate validity.
read_date
if requested
The data extraction date. The date is encoded using ISO 8601 UTC (timezone) date format (example: 2017-04-01T19:43:37+0000).
nationality_number
if requested
The Belgian National Register Number.
os
if requested
The device operating system. The returned values will be "ANDROID" or "iOS"
appName
if requested
The application name.
appRelease
if requested
The application current release.
deviceLabel
if requested
The name of the device.
debugEnabled
if requested
"True" if debug mode has been activated; otherwise "false".
deviceId
if requested
The device identifier.
osRelease
if requested
The version of the OS running on your device.
manufacturer
if requested
The brand of the device manufacturer.
hasSimEnabled
if requested
It tells you if a SIM card is installed in the device, or not. The returned value is always "true" as long as ITSME® can't be installed on tablets.
deviceLockLevel
if requested
smsEnabled
if requested
rooted
if requested
The returned value is always "false" as long as ITSME® can't be used on a jailbreaked/rooted device.
imei
if requested
The device IMEI value.
deviceModel
if requested
The model of the device.
sdkRelease
if requested
securityLevel
if requested
The security level used during transaction. The returned values could be "SOFT_ONLY", "SIM_ONLY" or "SIM_AND_SOFT".
bindLevel
if requested
It tells you if the User account is bound to a SIM card or not, at the time the transaction occurred. The returned values could be "SOFT_ONLY", "SIM_ONLY" or "SIM_AND_SOFT".
mcc
if requested
The Mobile Country Code. The returned value is an Integer (three digits) representing the mobile network country.
e-ID Picture
if requested

Mapping the User

To sign in successfully in your web desktop, mobile web or mobile application, a given user must be provisioned in OpenID Connect and then mapped to a user account in your database. By default, your application Server will use the subject identifier, or “sub” claim, in the ID Token to identify and verify a user account. Typically, the “sub” claim is a unique string that identifies a given user account. The benefit of using a “sub” claim is that it will not change, even if other user attributes (email, phone number, etc) associated with that account are updated.

The “sub” claim value must be mapped to the corresponding user in your application Server. If you already mapped this “sub” to an account in your application repository, you should start an application session for that User.

If no user record is storing the “sub” claim value, then you should allow the User to associate his new or existing account during the first sign-in session.

All these flows are depicted in the ITSME® B2B portal.

In a limited number of cases (e.g. technical issue,…) a user could ask ITSME® to ‘delete’ his account. As a result the specific account will be ‘archived’ (for compliancy reasons) and thus also the unique identifier(s) (e.g. “sub”), used to interact with the different Service Providers the specific users is active with, will be automatically deleted in our database.

If the same user would opt to (re)create an ITSME® afterwards, he will need to re-bind his ITSME® account with your application server (as the initial identifier is no longer valid as explained before). To re-bind his ITSME® account one of the above scenario should be used. After successful (re)binding you will need to overwrite the initial reference with the new ‘sub’ claim value in your database.

Appendixes

{ "applinks": { "apps": [], "details": [ { "appID": “JHGFJHHYX.com.facebook.ios", "paths": [ "*" ] } ] } }

Integration is going to be pretty straightforward, all details can be found in below steps (as documented on Universal Links official documentation):

  • Register your app at developer.apple.com.
  • Enable ‘Associated Domains’ on your app identifier.
  • Enable ‘Associated Domain’ on in your Xcode project.
  • Add the proper domain entitlement and make sure the entitlements file is included at build: Xcode will do it automatically by itself.
  • Create the ‘apple-app-site-association’ file (AASA). The AASA file contains a JSON object with a list of apps and the URL paths on the domain that should be included or excluded as Universal Links.
    The JSON object will contain:
Parameter
appID Built by combining your app’s Team ID (it should be retrieved from https://developer.apple.com/account/#/membership/) and the Bundle Identifier. In the example attached, JHGFJHHYX is the Team ID and com.facebook.ios is the Bundle ID.
paths Array of strings that specify which paths are included or excluded from association. Note: these strings are case sensitive and that query strings and fragment identifiers are ignored.
  • Upload the ‘apple-app-site-association’ file to your HTTPS web server for the redirection URI communicated in the Authentication Request. The file can be placed at the root of your server or in the .well-known subdirectory.

While hosting the AASA file, please ensure that the AASA file:

  • is served over HTTPS.
  • uses application/json MIME type.
  • don’t append .json to the apple-app-site-association filename.
  • has a size not exceeding 128 Kb (requirement in iOS 9.3.1 onwards)

  • Check if the AASA file is valid and is accessible by using the following link.
  • Add an entitlement to all redirect URI that the your app need to supports. In Xcode, open the Associated Domains section in the Capabilities tab and add an entry for each Redirect URI that your app supports, prefixed with `applinks`.
    To match all subdomains of an associated redirect URI, you can specify a wildcard by prefixing `*.` before the beginning of a specific Redirect URI (the period is required). Redirect URI matching is based on the longest substring in the `applinks` entries. For example, if you specify the entries `applinks:*.mywebsite.com` and `applinks:*.users.mywebsite.com`, matching for the redirect URI `emily.users.mywebsite.com` is performed against the longer `*.users.mywebsite.com` entry. Note that an entry for `*.mywebsite.com` does not match `mywebsite.com` because of the period after the asterisk. To enable matching for both `*.mywebsite.com` and `mywebsite.com`, you need to provide a separate `applinks` entry for each.

Apple doc says to limit this list to no more than about 20 to 30 domains

  • Update the app delegate to respond appropriately when it receives the `NSUserActivity` object. After all above steps are completed perfectly, when the User click a universal link, the app will open up and the method "application:continueUserActivity:restorationHandler" will get called in "Appdelegate". When iOS launches the the app after a User taps a universal link, you receive an "NSUserActivity" object with an "activityType" value of "NSUserActivityTypeBrowsingWeb". The activity object’s "webpageURL" property contains the redirect URI that the user is accessing. The webpage URL property always contains an HTTPS URL, and you can use "NSURLComponents" APIs to manipulate the components of the URL.
    For getting the URL parameters, use the function aside.

    Also if you want to check if the app had opened by clicking a universal link or not in the `didFinishLaunchingWithOptions` method below.
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> Bool { print("Continue User Activity called: ") if userActivity.activityType == NSUserActivityTypeBrowsingWeb { let url = userActivity.webpageURL! print(url.absoluteString) //handle url and open whatever page you want to open. } return true }
//playground code.. var str = “https://google.com/contents/someotherpath?category=series&contentid=1562167825" let url = URL(string: str) func queryParameters(from url: URL) -> [String: String] { let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) var queryParams = [String: String]() for queryItem: URLQueryItem in (urlComponents?.queryItems)! { if queryItem.value == nil { continue } queryParams[queryItem.name] = queryItem.value } return queryParams } // print the url parameters dictionary print(queryParameters(from: url!)) //It will print [“category”: “series”, “contentid”: “1562167825”]
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [ UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { var isUniversalLinkClick: Bool = false if launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey] { let activityDictionary = launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey] as? [AnyHashable: Any] ?? [AnyHashable: Any]() let activity = activityDictionary[“UIApplicationLaunchOptionsUserActivityKey”] as? NSUserActivity ?? NSUserActivity() if activity != nil { isUniversalLinkClick = true } } if isUniversalLinkClick { // app opened via clicking a universal link. } else { // set the initial viewcontroller } return true }

The App Links Assistant in Android Studio can help you create intent filters in your manifest and map existing URLs from your website to activities in your app. Follow below steps to configure the App links (as documented on App Links official documentation):

  • Add the intent filters to your manifest. Go through the your manifest and select Tools > App Links Assistant. Click Open URL Mapping Editor and then click Add at the bottom of the URL Mapping list to add a new URL mapping.
  • Add details for the new URL mapping:
    • Entering your redirect URI in the "host" field.
    • Add a "path", "pathPrefix", or "pathPattern" for the redirect URIs you want to map. For example, if you have a recipe-sharing app, with all the recipes available in the same activity, and your corresponding website's recipes are all in the same "/recipe directory", use "pathPrefix" and enter "/recipe". This way, the redirect URI http://www.recipe-app.com/recipe/grilled-potato-salad maps to the activity you select in the following step.
    • Select the Activity the redirect URI should take Users to.
    • Click OK.
  • The App Links Assistant adds intent filters based on your URL mapping to the "AndroidManifest.xml" file, and highlights it in the "Preview" field. If the you would like to make any changes, click Open "AndroidManifest.xml" to edit the intent filter.

To support more links without updating the app, you should define a URL mapping that supports future redirect URIs.

  • To verify the URL mapping works properly, enter a URL in the Check URL Mapping field and click Check Mapping. If it's working correctly, the success message shows that the URL entered maps to the activity you selected.
  • Handle incoming links. Once you have verified that the URL mapping is working correctly, you MUST add the logic to handle the intent he created.
    • Click Select Activity from the App Links Assistant.
    • Select an activity from the list and click Insert Code.

    The App Links Assistant adds code to the activity's Java file, similar to the one aside.

    However, this code isn't complete on its own. You MUST now take an action based on the URI in , such as display the corresponding content. For example, for the recipe-sharing app, the code might look like the sample aside.
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... handleIntent(getIntent()); } protected void onNewIntent(Intent intent) { super.onNewIntent(intent); handleIntent(intent); } private void handleIntent(Intent intent) { String appLinkAction = intent.getAction(); Uri appLinkData = intent.getData(); if (Intent.ACTION_VIEW.equals(appLinkAction) && appLinkData != null){ String recipeId = appLinkData.getLastPathSegment(); Uri appData = Uri.parse("content://com.recipe_app/recipe/").buildUpon() .appendPath(recipeId).build(); showRecipe(appData); } }
  • Associate the app with the redirect URI. After setting up URL support for your app, the App Links Assistant generates a Digital Asset Links file you can use to associate his website with your app. As an alternative to using the Digital Asset Links file, you can associate your site and app in Search Console. To associate the app and the website using the App Links Assistant, click Open the Digital Asset Links File Generator from the App Links Assistant:
  • Enter your Site domain and Application ID.
  • To include support in your Digital Asset Links file for Smart Lock for Passwords, select Support sharing credentials between the app and the website and enter your site's login URL. This adds the following string to your Digital Asset Links file declaring that your app and website share sign-in credentials: "delegate_permission/common.get_login_creds".
  • Specify the signing config or select a keystore file. Make sure to select the right config or keystore file for either the release build or debug build of your app. If you want to set up his production build, use the release config. If you want to test his build, use the debug config.
  • Click "Generate Digital Asset Links" file.
  • Once Android Studio generates the file, click "Save file" to download it.
  • Upload the "assetlinks.json" file to redirect URI site, with read-access for everyone, at "https:///.well-known/assetlinks.json".
  • Click "Link and Verify" to confirm that you've uploaded the correct Digital Asset Links file to the correct location.

The system verifies the Digital Asset Links file via the encrypted HTTPS protocol. Make sure that the assetlinks.json file is accessible over an HTTPS connection, regardless of whether your app’s intent filter includes https.

Security levels and context data

Depending on the required level of assurance your application MUST ensure the correct ‘security level’ is requested. Two ‘security levels’ are supported – ‘basic’ and ‘advanced’. Opting for ‘advanced’ will result in an ITSME® code entry being enforced to validate the specific transaction (even if the user has activated touch ID/fingerprint). With the ‘basic’ level also touch ID/fingerprint next to the ITSME® code are supported to validate the specific transaction.

The following table defines the different possible scenarios:

Security level Login Share Data
basic Allowed Allowed
advanced Allowed Allowed

Next to the security levels, your application MAY also request additional security data to determine the context in which the transactions have been executed. The security data elements, alone or in combination with each other, indicate a given risk exposure. By providing these elements, ITSME® allows you to detect fraud attempts or effective fraudulent transactions. The security data elements that MAY be used to associate a risk exposure to a specific transaction are available in the section Capturing claims from the userInfo Endpoint.

Using request_uri parameter

The “request_uri” parameter enables the Authentication Requests to be passed by reference, meaning that the Request Object value is retrieved from the resource at the specified URL.

When the “request_uri” parameter is used, the OpenID Connect request parameter values contained in the referenced JWT supersede those passed using the OAuth 2.0 request syntax.

The following validations should be done when using the “request_uri” parameter:

  • The values for the "response_type" and "client_id" parameters MUST be filled in the Authentication Request, since they are REQUIRED in the OpenID Connect Core specifications. The values for these parameters MUST match those in the Request Object, if present.
  • Even if a "scope" parameter is present in the Request Object value, a "scope" parameter – containing the "openid" scope value to indicate to the underlying OpenID Connect Core logic that this is an OpenID Connect request – MUST always be passed in the Authentication Request.
  • The Request Object MAY be signed using the JSON Web Signature (JWS). If signed, the Request Object SHOULD contain the claims "iss" (issuer) and "aud" (audience) as members. The "iss" value SHOULD be your Client ID. The "aud" value SHOULD be "https://merchant.itsme.be/oidc/authorization".
  • The Request Object MAY also be encrypted using JSON Web Encryption (JWE). In this case, it MUST be signed then encrypted, with the result being a Nested JWT, as defined in the JSON Web Token (JWT) section.
  • You need to store the Request Object resource either locally or remotely at a URL the the Authorization Server can access. This URL is the Request URI, "request_uri".
  • The Request URI MUST contain the port 443 as in this example: https://test.itsme.be:443/p/test.
  • The Request URI value is a URL using the https scheme.

Enclosed you will find a non-normative example of an Authorization Request using the “request_uri” parameter:

Authentication Request:

GET /oidc/authorization HTTP/1.1 &response_type=code &client_id=MY_PARTNER_CODE &scope=openid service:TEST_code profile email &redirect_uri=https://test.itsme.be &request_uri=https://test.itsme.be:443/p/test

Raw Request Object (not signed, not encrypted): { "aud": "https://merchant.itsme.be/oidc/authorization", "scope": "openid service:TEST_code profile email", "redirect_uri": "https://test.itsme.be", "response_type":"code", "client_id":"MY_PARTNER_CODE", "acr_values":"tag:sixdots.be,2016-06:acr_advanced", "iss":"MY_PARTNER_CODE", "nonce":"A_VALID_NONCE", "state":"A_VALID_STATE", "claims":{ "userinfo":{ "tag:sixdots.be,2016-06:claim_eid":null, "tag:sixdots.be,2016-06:claim_city_of_birth":null } } }