OpenID Connect

aID has a basic implementation of OpenID Connect (OIDC), a layer buildt on top of OAuth 2.0 that makes common integrations easier by adding data about the user to the OAuth 2.0 response, so the caller doesn't have to implement support for a custom endpoint for getting that data right after getting the OAuth access_token.

To read more about OpenID Connect, click here:  https://openid.net/connect/ 

Everything you've read about our OAuth 2.0 implementation still applies, there are just a couple of extra tricks you need to trigger OIDC-mode:


Triggering OIDC-mode

To trigger OIDC-mode you need to request the openid scope, but before you can do this, your OAuth 2.0 client (In OIDC called a Relying Party (RP)) needs to have access to this scope. This must be configured server side by aID.

Once the openid-scope has been configured for the client, the client can act as a Relying Party. This is done by adding openid as a requested scope during authorization.


Example:

https://www.aid.no/api/oauth/authorize/www.glomdalen.no?client_id=c4feb4b3&response_type=code&redirect_uri=https%3A%2F%2Fwww.example.com%2Faid_login&scope=openid+uuid+name+email&nonce=somethingrandom

The important part here is the openid-part after scope=. aID now knows that you want to have an id_token included in the response of the token endpoint after authorization. The flow will be the same as for normal authorization.

Another thing to note is that you should add a nonce, which is a random string that you add to authorization, and later checks inside the id_token to make sure there is no man in the middle doing a replay attack. This is recommended, but not required.


Stealth mode

OpenID Connect defines a standardized mode of triggering what we call stealth mode, which you can read about in  🟢Single signon and signout . In OIDC, this is triggered by adding a prompt parameter to the authorization request with the value none. When this is done, the user will not be presented with any aID user interfaces, instead the user is returned to redirect_uri with an error if the user can not be authorized without presenting a user interface.

The following errors can occur:
Title
Title
login_required
The user is not currently logged in, so in a normal flow, the user would be presented with the login page.
consent_required
The user is logged in, but has not previously agreed to share aID data with the Relying Party. In a normal flow, the user would be presented with a page where the user accepts an agreement with the legal entity (Amedia, Aller etc.) owning the Relying Party.



Getting the id_token

After the user has completed authorization, the user is sent back to requsted_uri as per normal OAuth 2.0. In the URL you will find a grant code that you pass to the token URL to get the OAuth access token. The only difference in OIDC-mode is that the response for this service now includes id_token, which is a JWT containing claims about the user. These claims can be used instead of calling separate endpoints for getting the same data.


Example:

curl -H 'Authorization: Basic YzRmZWI0YjM6MWMzYjAwZDQ=' -F grant_type=authorization_code -F code=d34db33f -F redirect_uri=https://www.example.com/aid_login -X POST https://www.aid.no/oauth/token

See the details about this request in  🟢Authorization .

Now the response will look a little different than before:
{
"access_token": "d4bbad00",
"token_type": "bearer",
"scope": "id name email",
"created_at":1422988263,
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL3d3dy5haWQubm8vIiwiYXVkIjoiYzRmZWI0YjMiLCJzdWIiOiI1OWNiNjM3Mi1kM2RiLTExZTUtYWIzMC02MjU2NjI4NzA3NjEiLCJuYW1lIjoiRG9uYWxkIER1Y2siLCJleHAiOjE2NjE1MjI1ODgsImlhdCI6MTY2MTUyMTk4OCwibm9uY2UiOiJzb21ldGhpbmdyYW5kb20ifQ.BVzmVa3yiY9OxS_cuQh9pcSw0sEv7BQoFEzQPXla5mVxZfCndobICFlcQtMZtpH8m8H5uGmkMDbgDQWnyfZfO4mKXcpbKQh1I4-fx7pQZjKBCK_yGi0DKguwuj6EpEq6xi7Y_ZRyhRTH90_wTSfVB9ECou6kNoxZFjBAb93ucYySW-nw_iVEhp_rQFvCWpDpzQJC9Jlb_0vXNcApKso28d0p047fP97HGi_GLqk3PuRSyR6M3pi8nQ82jPkrOV_V4GGAReyFMQ-NdhFIao6lSn2LEiZuoAsAmp9HdcTEaJ7jzftu4YB6tRBZ36g0ZUuroXb2KXxx7drhJ5Eg1owpig"
}

The new part here is the id_token. This looks like random garbage, but is in fact an encoded JWT. This can be decoded, and the signature can be verified, into a JSON like this:
{
"iss": "https://www.aid.no/",
"aud": "c4feb4b3",
"sub": "59cb6372-d3db-11e5-ab30-625662870761",
"name": "Donald Duck",
"exp": 1661522588,
"iat": 1661521988,
"nonce": "somethingrandom"
}

Now we immediately know a lot about the user, without having to call any of the endpoints described in  🟢Services . And OpenID Connect defines most of these claims (attributes), so the response should be compatible accross different ID-providers.

In this response we see that the JWT was issued by aID for Relying Party (OAuth Client) with client_id c4feb4b3. The subject here is the aID user with uuid 59cb6372-d3db-11e5-ab30-625662870761, who is called Donald Duck.
The response also tells us when the JWT expires and it lists the nonce, which should be verified to be the same as sent in the authorization request.

The token_id also contains a crypto-part describing how the JWT was signed:
{
"typ"=>"JWT",
"alg"=>"RS256",
"kid"=>"5ca1ab1e"
}

Here we can se that this is a JWT signed using the RS256 algorithm using a key with ID 5ca1ab1e.


Public key

The signature of the JWT should be verified to match our public key. The key can be downloaded from this URL:
https://www.aid.no/oauth/discovery/keys

The response will be a JSON containing a list of keys. One of them should match the kid of the crypto-part of the JWT.

Example response:
{
"keys": [
{
"kty": "RSA",
"kid": "5ca1ab1e",
"e": "AQAB",
"n": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0/IzW7yWR7QkrmBL7jTKEn5u+qKhbwKfBstIs+bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW/VDL5AaWTg0nLVkjRo9z+40RQzuVaE8AkAFmxZzow3x+VJYKdjykkJ0iT9wCS0DRTXu269V264Vf/3jvredZiKRkgwlL9xNAwxXFg0x/XFw005UWVRIkdgcKWTjpBP2dPwVZ4WWC+9aGVd+Gyn1o0CLelf4rEjGoXbAAEgAqeGUxrcIlbjXfbcmwIDAQAB",
"use": "sig",
"alg":"RS256"
}
]
}

Claims

OpenID Connect lists a set of standard claims, some of which are implemented by aID. Others can be implemented upon request, even claims not defined by OIDC. The implementation utilizes our public user API, anything this API can output can easilly be mapped to claims.


Claims are closelly tied to scopes, so you need a certain scope to get certain claims.

Currently implemented claims:
Title
Title
Title
Title
Claim
Attribute
Description
Scope
iss
Issuer. Standard OpenID claim.
aud
Audience. Standard OpenID claim. Corresponds to client_id.
iat
Issued At. Standard OpenID claim.
exp
Expires At. Standard OpenID claim
nonce
Nonce given in authorization request. Standard OpenID claim.
sub
uuid
User's ID. Uniquelly and permanently identifies the current user.
uuid
name
name
User's name.
name
pse
tracking_key
Pseudonym key used for tracking user on websites.
tracking_key
email
email
User's email address
email
phone_number
phone
User's mobile phone number
phone
birthdate
birth_date
User's birth date
birth_date
picture
avatar
User's profile picture (uploaded or from Facebook, with fallback)
avatar
privacy_preferences
privacy_preferences
User's privacy preferences (allow_research_usage, connect_with_surveys, personalized_ads and personalized_content as boolean attributes).
privacy_preferences

access
access
List of sites the user has access to (list of attributes with site_domain and access_features)
access


Obtaining OpenID Provider Configuration Information

aID implements an OpenID Provider Configuration Information endpoint as specified here:  https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig 

The configuration can be obtained from this URL:

Example response:
{
"issuer": "https://www.aid.no/",
"authorization_endpoint": "https://www.aid.no/oauth/authorize",
"token_endpoint": "https://www.aid.no/oauth/token",
"revocation_endpoint": "https://www.aid.no/oauth/revoke",
"introspection_endpoint": "https://www.aid.no/oauth/introspect",
"userinfo_endpoint": "https://www.aid.no/oauth/userinfo",
"jwks_uri": "https://www.aid.no/oauth/discovery/keys",
"scopes_supported": ["uuid","name","avatar","openid","profile","id","email","phone","birth_date","tracking_key","access","external_accounts","privacy_preferences","groups","two_factor_enabled"],
"response_types_supported": ["code"],
"response_modes_supported": ["query","fragment","form_post"],
"grant_types_supported": ["authorization_code"],
"token_endpoint_auth_methods_supported": ["client_secret_basic","client_secret_post"],
"subject_types_supported": ["public"],
"id_token_signing_alg_values_supported": ["RS256"],
"claim_types_supported": ["normal"],
"claims_supported": ["iss","sub","aud","exp","iat","name","pse"]}

The details will change in the future when more stuff is added etc. But here are the most important parts:
Title
Title
authorization_endpoint
This is where you send the user to start OpenID/OAuth authorization
token_endpoint
This is the endpoint to call after the user returns to redirect_uri and you want to get an access token or OpenID token.
revocation_endpoint
This is where you can log the user out
userinfo_endpoint
Here you can get OpenID user info without doing a new authorization
introspection_endpoint
Call this if you need status information about an access token
jwks_uri
This is where you can get public keys to verify the OpenID JWT signature