What is OIDC and where and why it is used
If you have ever followed prompts like ’Login with Google’, you may have used OIDC without knowing it. The protocol is used for Single-Sign-On (SSO) authentication and can be difficult to understand with a lot of misleading information around. I hope to provide an introduction to this protocol so you understand what it does and how it works.
Solving the authentication problem
OIDC is built on top of OAuth 2.0. Before talking about Open ID Connect (OIDC), you should understand OAuth and how it solves the delegated authorisation problem. If you want to know more, read my article on OAuth now.
Whilst OAuth fixed the authorisation issue, another problem arose. Users were having to log in to many different sites and having lots of passwords to manage.
The solution to this problem is for a single service to manage the logged in/out (authentication) status of the user along with some important information about them. This service could then provide this user authentication status and information to other services.
This means that when the user logs on to this Single Sign On (SSO) service, they can then seamlessly access any service that is registered to the SSO service, without having to log in again.
Open ID Connect (OIDC) was developed to provide this SSO functionality.
OIDC
OIDC is a protocol based on top of OAuth.
Just to recap, OAuth allows a Client service to obtain an Access Token that allows the Client to access resources on behalf of the user (the Resource Owner) from the Resource Server. The Authorisation Server provides the Access Token and only does this after the user logs in and provides their consent.
The OIDC protocol utilises this OAuth flow to provide Single Sign On (SSO) across a number of services. The idea is that the OIDC protocol uses OAuth to obtain the user authentication status and information from the Authorisation Server.
OIDC Terminology
First we have to adjust our terminology as OIDC uses different terms to OAuth.
The diagram above shows the terms used by OIDC. The terms in [ ] are the equivalent names used by OAuth.
- End User — the user being authenticated (you)
- Relying Party — the application that is relying on the SSO server to provide the authentication status
- Open ID Provider — the SSO server that is managing the authentication status of the user as well as some basic information about the user
Note that the Resource Server plays no purpose in OIDC.
OIDC Flow
The OIDC protocol can use either the Authorisation Code Flow or the Implicit Flow. It can also use these in various ways. There is a great article on the other options here. I will explain one of these flows, so you can understand the principles of what is happening.
Like my description of OAuth, I will use a fictitious example. Let’s say we use an application called MyBrillioGame
. Let’s also say we have an application MyDoggyWorld
, which provides a Single Sign On (SSO) service for people who love Dogs!
The flow starts when I go to the MyBrillioGame
website and I see a button that says ‘Log on with MyDoggyWorld
’. This is my queue to use SSO.
I click on the button and the browser is redirected to MyDoggyWorld
with a request for access.
This redirection and request is the same as OAuth and is, in fact using OAuth. The small, hidden detail here is that in the scopes we are requesting, we include openid
as a requested scope. This tells MyDoggyWorld
that you would like an ID Token back (as well as an Access Token in this case).
As with the OAuth flow, if you are not logged in, MyDoggyWorld
will ask you to log in to MyDoggyWorld
. No credentials are passed to MyBrillioGame
.
Of course, if you are already logged in, it skips this step.
MyDoggyWorld
will ask you for consent for MyBrillioGame
to have access to your details and will normally provide a list of those details (eg: name, email address).
When you say yes (providing consent), MyDoggyWorld
will return an Authorisation Code.
Now MyBrillioGame
has an Authorisation Code, it can now exchange this for an Access Token and an ID Token.
Instead of getting back Access and Refresh Tokens, it gets back an ID Token as well.
MyBrillioGame
can now use this ID Token as proof that you are logged in to MyDoggyWorld
and can use it to log you in to MyBrillioGame
too.
Now you have logged in to MyBrillioGame
but only has to log in once, to MyDoggyWorld
, so you have no password to maintain for MyBrillioGame
. Now if you go to your other service, MyStickThrowGame
, when you click on the Log in with DoggyWorld
button, you repreat this flow but, as you are already logged in to MyDoggyWorld
, you do not have to log in. The result is that you now only have one password to maintain.
There is a downside to SSO. If your password gets compromised, then all your connected services are also compromised.
ID Token
Like an Access Token, the ID Token is a JSON Web Token (JWT, pronounced ‘jot’). You can read about the structure of JWTs in my article on OAuth.
Just to recap, a JWT has three parts:
- A JSON Object Signing and Encryption (JOSE) Header
- A payload
- A signature
The payload does not contain scopes and should not be used to gain access to the Resource Owner’s resources via the Resource Server.
An example of a payload can be seen below.
{
"iss": "http://my-doggy-world.woof",
"sub": "MyDoggyWorld-maxy-dog",
"aud": "MyBrilioGameId",
"exp": 1311292476,
"iat": 1311292476,
"name": "Maxy Dog",
"given_name": "Maxy",
"family_name": "Dog",
"gender": "female",
"birthdate": "2024-10-31",
"email": "mayx.dog@my-doggy-world.com",
"picture": "http://my-doggy-world.com/maxy-dog/me.jpg"
}
The items in the payload are known as claims because the end-user that the token represents claims these values. This does not mean that they are true but are values that the end-user has claimed about themselves.
In some systems claims may be validated and entered through systematic means bringing more validity to the claims.
The OIDC standard defines some of these claims. Any other claims should ensure they do not re-use these claims but should be namespaces, eg: MyDoggyWorld.favouriteKennel
.
Here are some of the standard claims, explained in terms of MyDoggyWorld
(see here for a full set):
sub - an identifier of the end-user according to MyDoggyWorld
name - the end-user's full name that can be used for display
given_name - self explanitory
family_name - self explanitory
preferred_username - the end-user's username (or their preferred one if more than one)
email - the end-user's email address
Even from this small set, you can see that the ID Token can be used to effectively log in a user into the MyBrilioGame
service.
UserInfo
In my descriptions of OAuth and this one on OIDC, I have omitted some of the details about the different endpoints involved with these protocols.
There are three important ones:
/authorize
— used to start the OAuth flow
/token
— used to obtain a token from the authorisation code
/userinfo
— used to obtain information about the user
Note that these may be different for different OAuth/OpenID Providers. Most provide an end point called
.well-known/openid-configuration
that provides a list of all the endpoints to use for that specific provider.
I want to talk about the last one /userinfo
. This endpoint provides information about the user. You may be wondering why we need this if we have the ID Token.
There are differences between the ID Token and userinfo
endpoints:
- ID Tokens are a point in time and prove the user is present when it is obtained whereas
userinfo
can retrieve information about the user even if they are offline. - The information in the ID Token may be limited and you may use
userinfo
to obtain more information about the user. - You need an OAuth Access Token to access the
userinfo
endpoint so it is likely that you have an ID Token already. If the ID Token gives you the information you require, there is no need to suffer the delays from another REST API call to theuserinfo
endpoint. - As an ID Token is a point in time token, it is not possible to revoke the information associated with it. When using
userinfo
, you can revoke the Access Token and remove the ability to access fresh information.
Logging Out
Before we leave the subject of OIDC, there is one topic we need to understand — logging out.
If I have logged in to MyBrillioGame
by logging in to MyDoggyWorld
, how do I log out and what does logging out even mean?
There are two ways to log out:
Logout 1 from Relying Party
In this case you decide to log out from the MyBrillioGame
application.
Now there are two things that this can mean:
- Please log out from
MyBrillioGame
only - Please log out from
MyBrillioGame
and fromMyDoggyWorld
Only the designer of the MyBrillioGame
can decide which to do and may give you both options.
In the case of #1, the MyBrillioGame
developer can simply delete the MyBrillioGame
session and delete the ID Token, Access Token and Refresh Token, effectively logging you out.
In the case of #2, MyBrillioGame
first sends a request to the MyDoggyWorld
Open ID Provider requesting the user is logged out of that service too (including the Access Token for security). After this it then does the same thing as case #1.
Logout 2 from the Open ID Provider
In this case, you go to the MyDoggyWorld
application and log out.
Like logout 1, there are two scenarios:
- Please log out from
MyDoggyWorld
only (leaving other services logged in) - Please log out from
MyDoggyWorld
and from all connected services (eg:MyDoggyWorld
)
In the case of #1, MyDoggyWorld
deletes it session information session and deletes the ID Token, Access Token and Refresh Token, effectively logging you out.
In the case of #2, MyDoggyWorld
first sends a request to all Relying Parties requesting the user is logged out of that service. After this it then does the same thing as case #1. This requires the Relying Party to have their own logout endpoint and to have a way to secure that endpoint.
This logging out of Relying Parties is known as Federated Logout.
Alternative
Rather than implementing the callback in MyBrillioGame
, you can use the OAuth Resource Server to provide online presence information in each payload that it returns to the game.
A further option is to exclude the offline
scope in the Access Token. This then requires the Resource Server to ensure you are online (ie: logged in to the MyDoggyWorld
service) before granting access to the resource. If you are logged out, MyBrillioGame
will receive a 403 response which it can take to mean that you should be logged out.
Summary
Building on top of the OAuth protocol, we saw how Open ID Connect (OIDC) allows you to obtain information about the logged in user.
We looked at how the OIDC terminology differs from OAuth but how the flow works in a similar fashion.
Finally we looked at how you can track the session state by managing the logout events.
If you found this article of interest, please give me a clap as that helps me identify what people find useful and what future articles I should write. If you have any suggestions, please add them in the comments section.