OIDC Integration Guide

1. What Is OIDC

OpenID Connect is a simple identity layer on top of the OAuth 2.0 protocol. It enables clients to verify the identity of users based on the authentication performed by OAuth 2.0 authorization servers, as well as to obtain profile information about the user using REST.

The following sequence diagram demonstrates the hight level OpenID Connect flow:

 

How the token exchange is actually performed is determined by the grant type that the “Relaying Party” is requesting. At Audkenni we only support the “Authorization Code with PKCE” flow as can be seen in the sequence diagram below:

 

More details about this flow can be read here.

2. Integration

For OIDC integration the OpenID Provider (Audkenni) and the Relying Party first need to exchange their endpoints and credentials which each other.

 

2.1. Information provided by the OpenID provider:

The endpoints of the OpenID Provider are static and can be found here (together with other information about the Audkenni provider). The most important endpoints are:

Next to that, the OpenID Provider will provide a client_id and possibly a client_secret to the Relying Party

 

2.2. Information provided by the Relying Party:

The Relying Party needs to provide the following information

  • redirect_uri’s

  • If the client is confidential or public.

    • The main difference relates to whether or not the application is able to hold credentials (such as a client ID and secret) securely. e.g a javascript only client is considered public as the end-user will be able to see all the information exchanged between the Relying Party and the OpenID provider including credentials.


3. Setup

In some cases, the Relying Party is also an OpenID provider that received a request from other Relying Parties and relies on Audkenni for the actual authentication. This scenario is seen in the picture below.

 

In this case, Audkenni mandates that the information about the original Relying Party (RelatedPartyParty) is provided in the authorization request as the first attribute of the RELATEDPARTY scope url parameter, e.g.:

1 scope=openid profile signature RELATEDPARTY:exampleclient

An example full authorize request would look as follows:

1 2 3 4 5 6 curl -X GET \ 'https://idp-dev.audkenni.is:443/sso/oauth2/realms/root/realms/audkenni/authorize?\ client_id=exampleclient&response_type=code&scope=openid%20profile%20signature\ %20RELATEDPARTY:exampleclient&\ code_challenge=0KOfLdeXVo4BKJ1oJJEOEegfseVjv5A9-dn9sXTji48\ &code_challenge_method=S256&state=abc123&redirect_uri=http://localhost:8080'

3.1. Providing the login message

The message that the user receives during authentication (e.g. on his phone/app/nexus card) can also be provided in the authorize request as the second attribute of the RELATEDPARTY scope url parameter. The message has to be provided in base64 encoded format.

e.g

1 scope=openid profile signature RELATEDPARTY:exampleclient:TG9naW4gdG8gZXhhbXBsZSBjbGllbnQ=

An example full authorize request would look like this

1 2 3 4 5 6 curl -X GET \ 'https://idp-dev.audkenni.is:443/sso/oauth2/realms/root/realms/audkenni/authorize?\ client_id=exampleclient&response_type=code&scope=openid%20profile%20signature\ %20RELATEDPARTY:exampleclient:TG9naW4gdG8gZXhhbXBsZSBjbGllbnQ=\ &code_challenge=0KOfLdeXVo4BKJ1oJJEOEegfseVjv5A9-dn9sXTji48&code_challenge_method=S256\ &state=abc123&redirect_uri=http://localhost:8080'

If no message is provided in the RELATEDPARTY scope then the user will receive the message “Login to Audkenni”.

3.2. Influencing the login flow

The login flow the user experiences can be influenced by adding the “acr_values“ parameter in the authorize request. At the moment the following values are supported

  • default

    • In this case, the default login flow would be presented in which the user can choose the authentication method

  • nexus

    • In this case, only the nexus personal card authentication option is shown

  • sim

    • In this case, only the Sim card authentication option is shown 

An example authorizes request where the sim card option is enforced looks like this:

1 2 3 4 5 6 curl -X GET \ 'https://idp-dev.audkenni.is:443/sso/oauth2/realms/root/realms/audkenni/authorize?\ client_id=exampleclient&response_type=code&scope=openid\ %20profile%20signature%20RELATEDPARTY:exampleclient:TG9naW4gdG8gZXhhbXBsZSBjbGllbnQ=\ &code_challenge=0KOfLdeXVo4BKJ1oJJEOEegfseVjv5A9-dn9sXTji48&code_challenge_method=S256\ &state=abc123&redirect_uri=http://localhost:8080&acr_values=sim

→ Response

The end result of the oauth2 flow is two JWT tokens: the access_token and the id_token. The user information can be found in the following attributes of the id_token:

  • nationalRegistryId

    • The social security number

  • certificate

    • The certificate generated by the authenticator as a result of the user authentication

  • name

    • The display name of the user

As a reference, a complete payload of a (decoded) id_token looks as follows:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 { "at_hash": "B9S_gwle5CHxi5wX6BaY8g", "sub": "2963785c-b8cc-490e-8d7e-054f7538383b", "signature": "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", "auditTrackingId": "5d5aec42-65c2-484a-898f-0517415e32d5-337150", "iss": "https://idp-dev.audkenni.is:443/sso/oauth2/realms/root/realms/audkenni", "tokenName": "id_token", "aud": "exampleclient", "c_hash": "fkBNmAssGpWBsw_g-cncIw", "acr": "0", "nationalRegisterId": "0101303369", "org.forgerock.openidconnect.ops": "hN7HsJ_MOT5BJJazBsyRRaIQ4GQ", "s_hash": "bKE9UspwyIPg8LsQHkJaiQ", "azp": "exampleclient", "auth_time": 1575010950, "name": "Gervimaður Asía", "realm": "/audkenni", "exp": 1575014561, "tokenType": "JWTToken", "iat": 1575010961 }

4. Reference integration

A postman collection that replicated the oauth2 flow can be found here.