Want to know how OIDC works? Read on and find it out.
This is a series of blogs exploring OAuth and OIDC:
OAuth 2.0 Explained in Simple Words - Part I: What and Why
OAuth 2.0 Explained in Simple Words - Part II: OAuth 2.0 Flows, Authorization Code Flow and Client Credentials Flow
OAuth 2.0 Explained in Simple Words - Part III: OAuth 2.0 Flows, PKCE Flow
OIDC Explained in Simple Words - Part I: OIDC as an OAuth 2.0 Enhancement
OIDC Explained in Simple Words - Part II: OIDC as an Modern SSO Standard
Note: Before jumping on OIDC, it's better to have some understanding on OAuth 2.0 . You can check out OAuth 2.0 Explained in Simple Words series, which is a fairly complete tutorial on OAuth 2.0.
1. What OIDC (OpenID Connect) is
OIDC stands for "OpenID Connect". It is built on top of OAuth 2.0 protocol with an added Identity Layer, meaning OIDC is a superset of OAuth 2.0. In simple words, it allows another token - ID Token (Identity Token) to be returned together with the Access Token. While Access Token is used to access some resources, ID Token itself contains the User Information who has authenticated to the Authorization Server.
2. Why OIDC
Generally speaking, the whole point of OAuth 2.0 is for Client to get an Access Token so that it can access some resources. This works well for privilege delegation like explained in OAuth 2.0 Explained in Simple Words.
However, that Access Token does NOT contain any User Information (e.g. username, email, role...) who has authenticated to the Authorization Server and this User Information is often critical for a lot of functions in a system. Hence, after the OAuth 2.0 protocol came out and became popular, technology groups started to realize that there is a strong need to obtain that User Information somewhere during the process of running OAuth 2.0 flows.
Then the idea is why not just add another token that contains the User Information and return it together with the Access Token, as OAuth 2.0 protocol already popular? So the ID Token is added when Access Token is returned. Beyond just adding the ID Token, we need make it more comprehensive and become a standard so that everyone can follow it and hence, the birth of OIDC.
3. Understanding OIDC
Since OIDC is OAuth 2.0 under the hood, the core parts are the same for both two (such as grant types). Yet, there are still some naming changes and extensions in OIDC compared to OAuth 2.0.
3.1 Roles
The Authorization Server in OAuth 2.0 is renamed as OIDC Provider (also called Identity Provider or simply IDP).
The Client in OAuth 2.0 is renamed as Relying Party (RP).
Some of the terms are used interchangeably as in nature, they are the same.
3.2 Use of JWT
In OAuth 2.0, JWT is pretty much the go-to format for Access and Refresh Tokens. In OIDC, an ID Token is always a JWT token. Nowadays, all tokens are pretty much JWT token and that includes Access Token, ID Token and Refresh Token.
3.3 Standardized Scope
Scope in OAuth defines the level of privileges of an Access Token. When Client registers with Authorization Server, it needs to define the available scope list and there is no standard on that, meaning any client can define what ever values they want.
OIDC addresses scopes to the ID Token specifically. It provides some standard frequently used scopes while allowing custom scopes. Remember scope can be a list of string values and whenever a scope value is specified, the corresponding claims (or attributes) are returned in the ID Token.
Here are a list of the predefined standard scopes:
Scope | Required | Description |
---|---|---|
openid | Yes | default mandatory scope; returns a 'sub' claim which represents a unique identifier for the authenticated user |
profile | No | returns User's profile claims such as name, first_name, last_name... |
No | returns email claim and email_verified, which is a boolean |
3.4 ID Token
The ID Token is JWT format and its payload includes a list of claims (attributes). Here are some basic ones.
ID Token Claim | Meaning |
---|---|
sub | Subject - Identifier for the User at the Issuer |
iss | Issuer - which authority issued this ID Token |
aud | Audience - which Client the ID Token was generated for |
iat | Issue Time - when the ID Token was generated |
exp | Expiration Time - when the ID Token is set to expire |
acr | Authentication Context Reference - The security context values requested for Authentication |
User email |
For a more detailed list, you can check https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
3.5 OIDC Grant Flows
The grant flows for OIDC is the same with OAuth 2.0 as described in OAuth 2.0 Explained in Simple Words
Authorization Code
Client Credentials
PKCE
Device Code
Refresh Token
Implicit (deprecated)
User Password (deprecated)
Those flows can be categorized into two groups: human-to-server and server-to-server
Since ID Token is addressed to a User, the ID Token won't be returned in the server-to-server call, as there is no User authentication happening.
From the list above, Authorization Code and PKCE grant flows are the main ones used to get an ID Token. Although Device Code flow involves a user authentication, but ID Token is NOT usually used in the flow. Client Credentials and Refresh Token flows are server-to-server call, so no ID Token will be returned. Implicit and User Password flows involve User, but is deprecated due to security concerns and shouldn't be used for modern platforms.
3.6 Endpoints
Besides the original OAuth 2.0 endpoints (e.g. token introspection), there are some other endpoints worth mentioning as well.
Userinfo Endpoint
New to OIDC this endpoint allows you to make a request using an appropriate Access Token to retrieve identity information (claims) about the authenticated User. Here is an example:
{
"sub":"uid4BTXdCDI6TV4m3g3",
"name":"John Doe",
"first_name":"John",
"last_name":"Doe",
"locale":"en-US",
"updated_at":1311280970,
"email":"john.doe@example.com",
"email_verified":true,
"address":{
"street_address":"123 xxx Blvd.",
"locality":"Boston",
"region":"MA",
"postal_code":"02115",
"country":"US"
},
"phone_number":"+1 (777) 888-9999"
}
JWKS (Json Web Key Set ) Endpoint
JWKS (pronounced 'jawks') is a set of keys containing the public keys used to verify any JWT issued by the Authorization Server and signed using the asymmetric encryption algorithm (e.g. RS256). Below is an example where the first entry is shown:
{
"keys":[
{
"alg":"RS256",
"kty":"RSA",
"use":"sig",
"x5c":["MIIC+DCCAeCgAwIBABIGjYW6hFpn2VBAMTGGN1c3Rvb..."],
"n":"yeNlzlub9codqEztjfU_SPCT1Axz6if3lHpq_g4Sz-cbe4....",
"e":"AQAB",
"kid":"NjVBRjY5MDlCMUIwNzU4RTA2QzZFM",
"x5t":"NjVBRjY5MDlCMUIwNzU4RTA2QzZFMDQ4QzQ2MDA"
}
]
...
}
Each property in the key is defined by the JWK spec
Property Name | Description |
---|---|
alg | The cryptographic algorithm used for the key |
kty | The cryptographic family name for the key |
use | How the key is supposed to be used; 'sig' means signature; 'enc' means encryption |
x5c | The x.509 cert chain. The first entry is used to verify the JWT signature. |
n | The modulus value for RSA the public key |
e | The exponent value for the RSA public key |
kid | The key id - a unique identifier for the key |
x5t | The thumbprint of the x.509 cert |
The /.wellknown Endpoint
The .wellknown endpoint (don't miss the dot) returns OIDC metadata about the Authorization Server or OIDC Server. This endpoint usually does NOT need any authentication. Here is an example:
{
"issuer":"https://authorization-server.com",
"authorization_endpoint":"https://authorization-server.com/oauth/authorize",
"token_endpoint":"https://authorization-server.com/oauth/token",
"userinfo_endpoint":"https://authorization-server.com/oauth/userinfo",
"registration_endpoint":"https://authorization-server.com/oauth/clients",
"jwks_uri":"https://authorization-server.com/jwks",
"response_types_supported":[
"code",
"code id_token",
"code token",
"code id_token token",
"id_token",
"id_token token"
],
"response_modes_supported":[
"query",
"fragment",
"form_post"
],
"grant_types_supported":[
"authorization_code",
"implicit",
"refresh_token",
"password"
],
"subject_types_supported":[
"public"
],
"id_token_signing_alg_values_supported":[
"RS256"
],
"scopes_supported":[
"openid",
"email",
"profile",
"address",
"phone"
],
"token_endpoint_auth_methods_supported":[
"client_secret_basic",
"client_secret_post",
"client_secret_jwt",
"none"
],
"claims_supported":[
"iss",
"ver",
"sub",
"aud",
"iat",
"exp",
"jti",
"auth_time",
"amr",
"idp",
"nonce",
"name",
"preferred_username",
"first_name",
"last_name",
"email",
"email_verified",
"profile"
],
"introspection_endpoint":"https://authorization-server/oauth/introspect",
"introspection_endpoint_auth_methods_supported":[
"client_secret_basic",
"client_secret_post",
"client_secret_jwt",
"none"
],
"revocation_endpoint":"https://authorization-server/oauth/revoke",
"revocation_endpoint_auth_methods_supported":[
"client_secret_basic",
"client_secret_post",
"client_secret_jwt",
"none"
]
}
4. Sum Up
In this POST, we looked at what OIDC protocol is and why it is needed. OIDC is an added identity layer on top of OAuth 2.0. In other words, OIDC is a superset of OAuth 2.0. Furthermore, we explored some of the import details about OIDC such as standardized scopes, ID Token, grant flows and various endpoints.
You can continue on OIDC Explained in Simple Words - Part II, where we look at SSO with OIDC and some modern integration patterns.