OpenID Connect explained

OpenID Connect is the new emerging standard for single sign-on and identity
provision on the internet. Its formula for success: simple JSON-based
identity tokens (JWT), delivered via the OAuth 2.0 protocol to suit web,
browser-based and native / mobile apps.

1. Local user authentication vs Identity Providers

Applications often need to identify their users. The simplistic approach is to
create a local database for the users’ accounts and credentials. Given enough
technical care this can be made to work well. However, local authentication can
be bad for business:

People find sign up and account creation tedious, and rightly so. Consumer
web sites and apps may suffer abandoned shopping carts because of that, which
means loss of business and sales.

For enterprises with many apps, maintenance of separate user databases can
easily become an administrative and security nightmare. You may want to put
your IT resources to better use.

The established solution to these problems is to delegate user authentication
and provisioning to a dedicated, purpose-built service, called an Identity
Provider (IdP).

Google, Facebook and Twitter, where many people on the internet are registered,
offer such IdP services for their users. A consumer web site can greatly
streamline user onboarding by integrating login with these IdPs.

In a enterprise, this would ideally be one internal IdP service, for employees
and contractors to log into internal apps. Centralisation has considerable
benefits, such as easier administration and potentially faster development
cycles for new apps. You may ask: Isn’t that going to create a single point of
failure? No, not when the IdP service is built for redundancy.

2. Enter OpenID Connect

OpenID Connect,
published in 2014, is not the first standard for IdP, but definitely the best
in terms of usability and simplicity, having learned from lessons from past
efforts such as SAML
and OpenID 1.0 and 2.0.

What is the formula for success of OpenID Connect?

Easy to consume identity tokens: Client apps receive the user’s identity
encoded in a secure JSON Web Token (JWT), called ID token. JWTs are
appreciated for their elegance and portability, with support for a range of
signature and encryption algorithms. All this makes JWT outstanding for the
job of ID tokens.

Based on the OAuth 2.0 protocol: Clients use OAuth 2.0 flows to obtain
ID tokens, designed to fit web apps as well as native / mobile apps. OAuth
2.0 also means one protocol for authentication and authorisation (obtaining
access tokens).

Simplicity: OpenID Connect is simple enough to integrate with basic apps,
but it also offers a number of features and security options to match
demanding enterprise requirements.

3. The identity token

The ID token
resembles the concept of an identity card, in a standard JWT
format, signed by the OpenID Provider (OP). To obtain one the client needs to
send the user to their OP with an authentication request.

Features of the ID token:

Asserts the identity of the user, called subject in OpenID (sub).

Specifies the issuing authority (iss).

Is generated for a particular audience, i.e. client (aud).

May contain a nonce (nonce).

May specify when (auth_time) and how, in terms of strength (acr), the user
was authenticated.

Has an issue (iat) and an expiration date (exp).

May include additional requested details about the subject, such as name and
email address.

Is digitally signed, so it can be verified by the intended recipients.

May optionally be encrypted for confidentiality.

The ID token statements, or claims, are packaged in a simple JSON object:

You can read more about the JWT data structure and encoding in RFC
7519.

4. How to request an ID token

Now that we know what an ID token is, how can a client, called
Relying Party (RP) in OpenID Connect, request one?

Authentication must take place at the identity provider, where the user’s
session or credentials will be checked. For that a trusted agent is required,
and this role is usually played by the web browser.

Browser popups is the preferred way for web apps to redirect the user to the
IdP. Mobile apps on platforms such as Android or iOS should launch the system
browser for that purpose. Embedded web views are not be trusted, as there’s
nothing to prevent the app from snooping on the user password. User
authentication must always occur in a trusted context separate from the app’s
context (e.g. the browser).

Note that OpenID Connect doesn’t specify how users should actually be
authenticated, this is left up to providers.

ID tokens are requested via the OAuth 2.0 protocol (RFC
6749), which has been a tremendous success
on its own. OAuth was originally devised as a simple authorisation mechanism
for apps to obtain access tokens for web APIs or other protected resources. It
has flows designed for all app types: traditional server-based web apps,
browser (JavaScript) only apps, and native / mobile apps.

So what are those flows, or paths, for obtaining ID tokens?

Authorisation code flow
— the most commonly used flow, intended for traditional web apps as well as
native / mobile apps. Involves an initial browser redirection to / from the
OP for user authentication and consent, then a second back-channel request to
retrieve the ID token. This flow offers optimal security, as tokens are not
revealed to the browser and the client app can also be authenticated.

Implicit flow
— for browser (JavaScript) based apps that don’t have a backend. The ID
token is received directly with the redirection response from the OP. No
back-channel request is required here.

Hybrid flow
— rarely used, allows the app front-end and back-end to receive tokens
separately from one another. Essentially a combination of the code and
implicit flows.

The OpenID Connect spec provides a nice comparison
of the three flows, reproduced here in a simplified form.

Flow property

Code

Implicit

Hybrid

Browser redirection step

✔

✔

✔

Backend request step

✔

✕

✔

Tokens revealed to browser

✕

✔

✔

Client can be authenticated

✔

✕

✔

5. Cool ID token uses

The ID token is versatile, and its use is certainly not limited to
just signing in users into apps:

Stateless sessions — Put into a browser cookie the ID token can be used
to implement lightweight stateless sessions. This does away with the need to
store sessions on the server side (in memory or on disk), which can be quite
a burden for apps that must scale well. The session cookie is checked by
validating the ID token. If the token has expired the app can simply ask the
OP for a new one via a silent prompt=none request.

Passing identity to 3rd parties — The ID token may be passed to other
components of the app or to backend services when knowledge of the user’s
identity is required, for example to log audit trails.

Token exchange — The ID token may be exchanged for an access token at
the token endpoint of an OAuth 2.0 authorisation server
(draft-ietf-oauth-token-exchange-03).
There are many real world scenarios when an identity document is required to
obtain access, for example when you check in at a hotel to get your room key.
Token exchange has uses in distributed and enterprise applications.

scope Used to specify the scope of the requested authorisation in OAuth.
The scope value openid signals a request for OpenID authentication and ID
token.

client_id The client identifier of the RP at the OP. This identifier is
typically obtained when the RP is registered with the OP, via the client
registration API, developer console, or some other method.

state Opaque value set by the RP to maintain state between request and
callback.

redirect_uri The RP callback URI for the authentication response.

At the OP, the user will typically be authenticated by checking if they have a
valid session (established by a browser cookie), and in the absence of that, by
prompting the user to login. After that the user will typically be asked
whether they agree to sign into the RP.

The OP will then call the client redirect_uri with an authorisation code (on
success) or an error code (if access was denied, or some other error occurred,
such a malformed request was detected).

The RP must validate the state parameter, and use the code to proceed into
the next step - exchanging the code for the
ID token.

Code flow: Step 2

The authorisation code is an intermediate credential, which encodes the
authorisation obtained at step 1. It is
therefore opaque to the RP and only has meaning to the OP server. To retrieve
the ID token the RP must submit the code to the OP, but this time a direct
back-channel request is needed. All this is done for two reasons:

To authenticate confidential clients with the OP before revealing the tokens;

To deliver the tokens straight to the RP, thus avoid exposing them to the
browser.

The client ID and secret are passed via the Authorization header. Apart from
HTTP basic authentication
OpenID Connect also permits authentication with signed JWT
assertions, which do not expose the client
secret with the token request, and hence offer better security.

The ID token is a JWT and must be carefully
validated
by the RP before it can be accepted.

Note that a bearer access token is also
included. This is to ensure the token response
is compliant with the OAuth 2.0 spec. For
basic OpenID authentication requests where only an ID token is requested this
access token is nominal and may be safely ignored. The access token however
comes into play when also requesting access to user profile data at the
UserInfo endpoint. More on this in the next chapter.

7. Claims (user info)

OpenID Connect specifies a set of standard
claims,
or user attributes. They are intended to supply the client app with consented
user details such as email, name and picture, upon request. Language
tags enable localisation.

If you’re an app developer, respect the user’s privacy and keep the requested
claims down to the very essential. This will increase your chances of user
conversion and will also ensure compliance with recent privacy laws.

Note that even if a user allows an app to access their identity, they may
choose to deny release of some claims. The app should be able to handle such
decisions gracefully.

OpenID providers may extend the standard JSON claims schema to include
additional attributes.
Enterprises may for instance define claims such as employee role, manager, and
department. The names of any additional claims should be prefixed by a URL to
create a safe namespace for them and prevent collisions.

8.1 Authorisation endpoint

This is the OP server endpoint where the user is asked to
authenticate and grant the client app access to the user’s
identity (ID token) and potentially other requested details, such as email and
name (called UserInfo claims).

This is the only endpoint where the user needs to interact with the OP, via a
user agent, which role is typically assumed by the web browser.

8.2 Token endpoint

The token endpoint authenticates the client app, then lets it exchange the
code received from the authorisation endpoint for an ID
token and access token.

The token endpoint it may also accept other OAuth 2.0 grant
types to issue tokens, for
example:

8.4 Optional endpoints

WebFinger —
Enables dynamic discovery of the OpenID Connect provider for a given user,
based on their email address or some other information.

Provider metadata —
JSON document listing the OP endpoint URLs and the OpenID Connect / OAuth 2.0
server features that it supports. Client apps can use this information to
configure their requests to the OP.

Provider JWK set — JSON document containing the provider’s public keys
(typically RSA) in JSON Web Key (JWK) format. These keys are used to secure
the issued ID tokens and other artifacts.

Client registration —
RESTful web API for registering client apps with the OP. Registration may be
protected (require pre-authorisation) or open (public).

Session management —
Enables client apps to check if a logged in user has still an active session
with the OpenID Connect provider. Also to facilitate logout.

10.2 How do OpenID providers authenticate users?

OpenID Connect leaves this entirely up to the particular IdP. Implementors may
use any method for authenticating users, or combine two methods for stronger
security (2FA).

Username / password

Hardware tokens

SMS confirmation

Biometrics

Etc.

The IdP may set the optional acr and amr claims in the ID
token to inform the client how the user has been authenticated.

Clients are also have control over authentication:

The optional prompt=login parameter will cause the user to be
(re)authenticated, even if they have a valid session (cookie) with the IdP.

With IdPs that support various authentication strengths, the application may
request stronger authentication using the optional acr_values parameter.

10.3 What is a bearer access token?

The access token resembles the concept of a physical token or ticket. It
permits the carrier access to a specific HTTP resource or web service, which is
typically limited by scope and has an expiration time.

Bearer access tokens are easy to use - whoever has them has a key to the
protected resource. For that reason they must always be passed around over a
secure channel (TLS / HTTPS) and stored securely.