# OIDC implementation

# Flows

OIDC lets developers authenticate users across websites and apps without having to own and manage password files. Authentication can be done in three different ways using OIDC:

  • The authorization code flow
  • The implicit flow
  • The hybrid flow

We have implemented two of them, the authorization code flow and the hybrid flow. These flows will be the ones described in this document. To learn more about the different flows and their differences, refer to the OIDC documentation (opens new window).

# Authorization code flow

The authorization code flow provides you with an authorization code. You can exchange the authorization code for an ID token, an access token and a refresh token (optional) at the token endpoint of our OIDC server.

This process provides the benefit of not exposing any tokens to the user agent (and possibly other malicious applications with access to the user agent). For the authentication server to trust the client before exchanging any authentication data regarding the end-user, the server can authenticate the client. The authentication code flow is therefore suitable for clients that can securely maintain a client secret between themselves and the OIDC authentication server.

The authorization code flow steps for performing authentication to log in the end-user (or to determine that the end-user is already logged in) are as follows:

  1. The user agent requests to be authenticated.
  2. The client prepares an authentication request and sends the request to the OIDC server.
  3. The authorisation server authenticates the end-user.
  4. The authorisation grant code is requested.
  5. The OIDC server obtains end-user consent (optional).
    1. If consent is asked for but denied, the end-user will not be authorised and will not be able to access their resources. The login will be stopped. The process will end at this step.
    2. If consent is asked for and given, the end-user will be authorised. The process continues with step 6.
  6. The OIDC server sends the end-user back to the client with an authorization code.
  7. The client requests a response using the authorization code at the token endpoint of our OIDC server.
  8. The client receives a response that contains an ID token, an access token and a refresh token (optional) in the response body (among other parameters).
  9. The client validates the ID token, retrieves the end-user's subject identifier and requests resources.

# Hybrid flow

The hybrid flow combines the implicit flow with the authorization code flow. With the hybrid flow, some tokens are returned from the authorization endpoint and others are returned from the token endpoint.

Here's a brief summary of how the hybrid flow works:

  1. The user agent requests resources.
  2. The client prepares an authentication request and sends it to the OIDC server.
  3. The authorisation server authenticates the end-user.
  4. The authorisation grant code is requested.
  5. The OIDC server obtains end-user consent.
  6. The authorisation server sends the end-user back to the client with an authorization code and, depending on the response type, one or more additional parameters.
  7. The client requests a response using the authorization code at the token endpoint of our OIDC server.
  8. The client receives a response that contains an ID token and an access token in the response body (among other parameters).
  9. The client validates the ID token and retrieves the end-user's subject identifier.

# Claims

At the heart of OIDC are claims; an attempt to standardise all the different pieces of information about an end-user. A claim may, for instance, be an end-user's surname or email address, which makes claims very similar to the concept of assertions in SAML. However, claims in OIDC are represented (as everything else in OAuth 2.0/OIDC) as JSON key-value pairs.

Where to get claims?

The OIDC specification details sources of claims: the ID token and the UserInfo endpoint.

The ID token is a signed JSON object (a JSON web token, or JWT) containing the authentication result. You can learn more about the ID token in the OIDC documentation (opens new window). Some claims in the ID token are optional and can be left out depending on how much information you want it to contain.

The UserInfo endpoint is a separate endpoint that accepts access tokens and returns information about the end-user. An access token represents an authorisation from the end-user to the client to perform actions on the end-user's behalf. Therefore, only information which the end-user has authorised should be returned. The UserInfo claims that can be returned are largely standardised but can be infinitely extended.

Note

We strongly recommend that you use only ID tokens for obtaining claims. Using UserInfo usually adds complexity for very little benefit.

# Signing keys

The signing key is a JSON web key (JWK) which contains the public part of an asymmetrical key pair. In general terms, a JWK is a JSON object that represents a cryptographic key.

Signing keys ("use": "sig") are published through JSON web key set (JWKS), a well-known URL available at your Signicat domain. Signicat signs each token with the private key on the authorisation server side.

To verify that a JWT token is valid and originated from the Signicat authorisation server, your application needs to verify the token’s signature using the public key published in the JWKS. Signature validation ensures that the token was issued by Signicat and that no one has tampered with the token.

# JSON web key set (JWKS)

A JSON web key set (JWKS) contains a set of keys containing the public keys that your application can use to validate any Signicat-issued token (JWT), like access and ID tokens.

Note that while the JWKS may contain multiple keys, you application needs to use only one JWK for to validate the token's signature.

The JWKS is available at a public endpoint in your Signicat domain. To find your JWKS endpoint:

  1. Go to https://<YOUR_SIGNICAT_DOMAIN>/auth/open/.well-known/openid-configuration.
  2. Locate the endpoint specified in the jwks_uri field.
  3. Go to the JWKS (jwks_uri) endpoint.

The JWKS endpoint contains a JSON with a list of keys for both:

  • Production signing keys
  • Sandbox signing keys

Sandbox signing keys

Sandbox keys are prefixed with “sandbox-”. For example, "kid": "sandbox-signing-key-...".

Learn more about JWK parameters in the RFC 7517 Internet Standards (opens new window).

# Key rotation

It is important to assume that the JWKS endpoint could contain multiple JWKs. In fact, an undetermined number of unordered keys are usually available and subject to change because of key rotation. Periodic key rotation ensures a higher level of security.

When validating a token consider the following:

  • If token signature validation fails, fetching the current key set will give a key set where one of the keys is the correct one.

  • New keys for token signing are published to the JWKS endpoint in advance of any changes to which key is used for signing. This is to let caching solutions prefetch the newly updated key set.

Signicat recommends that you refresh your replica or cache of signing keys regularly – the keys on our side will be rotated frequently.

For instance, you could refresh your cache when a kid (key identifier) is present in the JWKS but not present in your cache. Vice versa you may remove a key with a kid present on your side but not in the JWKS.

# Default signing and encryption

  • Encryption algorithm: AES-128
  • Supported key length: 2048-bit (4069-bit also supported)
  • Signature hash: SHA-256
What? Signing Encryption
ID token Always Optional, off by default
Access token Always Never
UserInfo response Optional, off by default Optional, off by default

Note:

Elliptic curve cryptography (ECC) key pairs are not supported at the moment. If your implementation requires this feature, contact Signicat Support at support@signicat.com.

# Endpoints

The following endpoint URLs are available for communicating with the OpenID Connect provider through Signicat.

# Authorization

The authorization endpoint performs the authentication of the end-user. You can find the full list of available request parameters in the 'Authentication Request' section (opens new window) of the OIDC documentation.

Example authorization request

"https://<YOUR SIGNICAT DOMAIN>/auth/open/connect/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&response_type=code&scope=openid%20profile&state=123&code_challenge=ABC123&code_challenge_method=S256&response_mode=query"

# acr_values

You can use acr_values to adjust how the authentication flow behaves. There are generic parameters (listed below) that work for all identity providers (IdPs), as well as IdP-specific parameters.

The format is a space-separated list of key-value pairs: acr_values=key1:value1 key2:value2. To specify multiple values for the same key, use the comma-separated format: acr_values=key1:value1a,value1b.

Example: acr_values=idp:idp_name,other_idp_name loa:high

Result: IdP will be pre-selected for the end-user; Level of Assurance is set to high.

Available parameters:

Name Description
idp Defines which IdP to use. This works in conjunction with login_hint.
loa Specifies the eIDAS Level of Assurance (LoA). Allowed values: low, substantial or high.
theme Specifies which theme to use.

# login_hint

You can use this login_hint to prefill end-user information that we send to the IdP, such as the end-user's national identification number. The format is a space-separated list of key-value pairs: login_hint=key1:value1 key2:value2, and so on.

The following options are available:

Name Description
nin Prefilled National identification number.
mobile Prefilled mobile phone number.
dateOfBirth Prefilled date of birth (YYYY-MM-DD).
email Prefilled email address.
username Prefilled username information.

You can find specific configuration examples for the following ID methods here:

`login_hint` and `acr_values` field format

Note that query parameters must be URL encoded (percent encoding).

For example, if you want to prefill end-user mobile numbers with login_hint, use login_hint=mobile:%2B447700900000 to represent the +44 7700900000 phone number.

# Token

To obtain an access token, an ID token and optionally a refresh token, the client sends a token request to the token endpoint to obtain a token response.

Example token request

curl -XPOST "https://<YOUR SIGNICAT DOMAIN>/auth/open/connect/token" -H "Content-Type: application/x-www-form-urlencoded" -H "Authorization: Basic czZCaGRSa3FOMzpnWDFmQmFOM2JW" -d "grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https://example.com"

Example token response

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
    "access_token": "eyJ ... Klmmm.emo ... NzBKFf.gaW8g ... Mzn5"
    "token_type": "Bearer",
    "refresh_token": "eyJ ... zcuUk.mow ... 7HmKmn.ggW8h ... Gz4g",
    "expires_in": 3600,
    "id_token": "eyJ ... zcifQ.ewo ... NzAKfQ.ggW8h ... Mzqg"
}

# UserInfo

To obtain the requested claims from the UserInfo endpoint, the client makes a request using an access token obtained through OpenID Connect authentication.

Example UserInfo request

curl -XPOST "https://<YOUR SIGNICAT DOMAIN>/auth/open/connect/userinfo" -H "Accept: application/json" -H "Authorization: Bearer fAAdL01c6QWDbPs9HrWHz5e7nRWVAnxqTTP7i88G"

Example UserInfo response for valid access token

HTTP/1.1200OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
    "sub": "bob"
    "given_name": "Bob",
    "name": "Bob Smith",
    "email": "bob@mycompany.com",
    "phone_number": "+1 (604) 55-555-66-777",
    "address": {"formatted": "123 Main St., Anytown, TX 77777"}}

# Error codes

We follow the OIDC and OAuth standards as closely as possible, which is also true when conveying error messages.

Errors on the authorization endpoint are primarily passed along as parameters on the redirect URI. These URL parameters are error and error_description. You can see a list of the Signicat-specific error codes here.

There will be some situations where it's not possible to use the redirect URI to pass along errors. In these cases we present an error page (opens new window). These types of errors are typically the result of an incorrect implementation or invalid configuration. These errors are typically not caused by our end-users.

Errors from the token and UserInfo endpoints are strictly defined in the OpenID Connect and OAuth protocol specifications:

  1. Token error response (opens new window)
  2. UserInfo error (opens new window)

Finally, there are standard HTTP status error codes which can, for instance, appear if there is a serious error in the solution (typically a 5xx server error) or if you are trying to access an incorrect URL (404). These will be what you would expect from any web service or API.

# Single sign-on (SSO)

Single sign-on (SSO) allows the end-user to establish their identity once without having to re-authenticate every time they access your services.

Levels of SSO

Signicat eID Hub supports two levels of SSO, at the OIDC server and Broker level.

This page describes only SSO at the OIDC server level. More information about SSO at the Broker level will follow soon.

# How it works

When the end-user first logs in with SSO, the Signicat OIDC server sets, and stores, an encrypted cookie that contains information about the end-user's device. Note that the SSO scope is set at the (Signicat) account level.

On subsequent logins, the Signicat OIDC server checks to see whether there is an existing SSO cookie. The SSO cookie validity and lifetime are verified on Signicat's backend side.

If a valid cookie is present, the end-user is automatically redirected to your application without being asked to re-authenticate.

# SSO in the Dashboard

When you create a new OIDC client, SSO is enabled by default.

You can control the cookie lifetime with the User SSO lifetime setting. The default value is 3600 seconds (1 hour).

To change the SSO session lifetime:

  1. Go to your OIDC client in the Dashboard (opens new window) and select Edit to view the client configuration.
  2. Navigate to the Advanced > Lifetimes tab.
  3. Edit the User SSO lifetime setting.
  4. Select Update to save and apply the changes.

# Forcing re-authentication

To force the end-user to re-authenticate every single time, use the URL parameter prompt=login in each authorisation request.

# Single log-out (SLO)

Single log-out (SLO) is a feature that allows the end-user to sign out of multiple authenticated sessions with a single action.

Signicat implements the OpenID Connect RP-Initiated Logout 1.0 (opens new window) standard for end-user logout.

OIDC level only

At the moment, the end-user will only be logged out of Signicat OIDC server. Any other potential SSO session at the application, IdP or Broker level will not be terminated (logout).

# Example of logout

To initiate logout you need to direct the end-user to the /auth/open/connect/endsession endpoint, as shown in the following example:

https://<YOUR_SIGNICAT_DOMAIN>/auth/open/connect/endsession?post_logout_redirect_uri=https://signicat.com&id_token_hint=eyJhb...QifQ...hLVNI8Q

You can customise the logout process by specifying the following query parameters:

  • id_token_hint (recommended). It's necessary to identify the end-user you want to log out. It should contain a valid ID Token as described in the next section.
  • post_logout_redirect_uri (optional). The URI you provide in the request must match the URI configured in the Post Logout Redirect URI setting of your OIDC client in the Dashboard.

# Providing an ID token

If you initiate a logout request without providing a valid ID token the end-user will be presented with a web page that prompts them to log out, instead of automatically logging them out.

The ID token provides the context necessary to log out the end-user in an automated way. Without this information, it is not possible to link the client and the end-user logout request. Therefore, without a valid ID token the end-user has to submit their consent to log out.

This also means you cannot use Post Logout Redirect URI or Automatic Redirect to Logout Url functionality.

# Automatic redirect after logout

After the end-user logs out, you can automatically redirect the end-user to a specific URL. You can control where to redirect the end-user with the Post Logout Redirect URI setting.

For security reasons, you need to meet the following conditions:

  • Provide valid id_token_hint and post_logout_redirect_uri in the request.
  • Enable Automatic Redirect to Logout Url in the URIs configuration of your OIDC client in the Dashboard.

Without these conditions the end-user gets redirected to a default confirmation logout screen.

# Finnish Trust Network (FTN) specifics

Due to requirements from Traficom, you are required to use Full Message-Level Encryption (MLE) for authentication with FTN.

There are two different ways to achieve this. The first is required and the second is only required in certain circumstances:

  1. Receiving encrypted responses from Signicat (required)
  2. Sending encrypted requests to Signicat (optional)

Important

If you are sending personally identifiable information (PII) as part of your request, you will also need to send encrypted requests. This is typically relevant if you are prefilling the end-user's national identification number (NIN).

Both these mechanisms are described in Advanced security considerations.

# External references

# OpenID Connect

# OAuth 2.0

Last updated: 18/04/2024 09:30 UTC