Why OpenID Connect and OAuth are not the same, and why you should never do without it.

10.08.2022Tom Trapp
Cloud oauth oidc accesstokens Authorization / Authentication Security

OAuth

Having already been introduced to SAML in my last TechUp, let’s travel further in history to the present and bump straight into OAuth. Open Authorisation (OAuth) is a protocol, or rather a login method, which was published in 2007 in version 1.0. In 2012, the successor version 2.0, which is not backwards compatible and is still widely used today, was published. From here on, OAuth always refers to OAuth 2.0. Developers from companies like Twitter and Google are behind OAuth. Over the years, OAuth 2.0 has been extended and adapted again and again with various RFCs.

It is important to mention that OAuth is primarily an authorisation protocol, and thus has nothing directly to do with authentication. The goal is to transfer user data between multiple platforms. A password is never transmitted in this process!

For example, a third party website may want to request profile information and pictures from Facebook on behalf of the user. This requires the user’s permission for the web application to retrieve profile data from Facebook. OAuth can secure and perform such authorisation. In doing so, Facebook retains full control over the data and no login information is exchanged. Specific time-limited permissions are given to the web application. This ensures, for example, that the third-party website is not allowed to perform any actions other than posting something on Facebook. The user is already logged in to both services and OAuth simply ensures that permissions between the two systems are checked by the user and then exchanged accordingly.

Technically, OAuth uses a token to transfer these special permissions.

Flow

A world without OAuth?

Figure: Source: By Devansvd - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=109591037

Surely nobody wants that! In the previous example, here our face-nova website would get the customer’s user data from Facebook in order to be able to query user information and photos there. Here, the user no longer has any control over what happens to his account or the like. The website has full access and can post clutter or request personal information.

The right way - with OAuth!

Figure: Source: By Devansvd - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=109591026

OAuth here offers the possibility for the user to give specific permissions to our face-nova website, such as only being able to read profile information and photos. Part of the flow is a step where the user gets listed the corresponding permissions (Authorization Request) and has to agree (Authorization Grant).

This is done via a special Access Token, which is issued by Facebook’s login service (Authorisation Server). The third-party website (the client, in our case face-nova) thus gains access to the profile information and photos (Resources), which are stored by Facebook (Resource Server).

Important Keywords

Resource Owner: Entity requesting access to a protected resource, classically the end user. Resource Server: The server on which the protected resource resides. This is able to grant access based on a JWT Access Token.

  • Client: The application (web, mobile, desktop or similar, also called Relying Party) that wants access to the protected resource of the resource owner.
  • Authorisation Server: Service that authenticates the resource owner and issues a token, classically the IdP (see IdP-SAML TechUp).
  • Consent: The input screen that the user sees, e.g. “Application X wants access and requests permissions X”.
  • JWT: JSON Web Token, type of token used to transfer the data (for more on this, see Stateless Sessions thanks to JSON Web Tokens.).
  • Grant Types: More than four different authorisation approval processes (authorisation code, implicit, resource owner password credentials, client credentials, etc.) to authenticate client and resource owner.
  • Scopes: The individual authorisations can be requested using different scopes.

So much for OAuth. or OAuth 2.0, now let’s build on this knowledge and take a closer look at OIDC!

OIDC

Open ID Connect is an authentication standard that uses OAuth 2.0 as a basis. The OpenID Foundation is behind the standard. As with SAML, OIDC is used to authenticate a user who has previously registered at a central point, the IDP, to other systems. The data transmission plays a central role here. In token-based authentication, user data and rights can be transferred directly in the token. Communication here takes place primarily between the IdP and the client, the so-called Relying Party.

Today, OpenID Connect is very widespread and almost all IdP systems support the standard. So let’s take a closer look at it now.

Tokens

Access Token

Access tokens are used to grant access to a resource. A resource here can be an API endpoint, a file, a database or similar. The Access Token was created by OAuth. The access token can be a simple string, but most often a JWT token is used here. An Access Token is usually only valid for a short time, so the Refresh Token is often used in combination with the Access Token (more on this later).

DO’s & DON’Ts

  • ❌ Access tokens are not used for authentication.
  • ✅ Access Tokens should only be used for authorisation.
  • ❌ It should not be possible to recognise the user via an access token; furthermore, it is not possible to tell whether the user is still logged in or not.

ID Token

The Identification Token is used to identify the user. What is special here is that the ID Token was not created by OAuth, but by OpenID Connect (OIDC). The ID token must always be in JWT format with header, payload/body and signature.

Basically, it consists of the following fields, among others:

  • sub: Subject; the unique identifier or ID of the user.
  • aud: Audience; the Client, i.e. the application for which the JWT was generated.
  • iss: Issuer; the issuer of the token (issuing authority).

The aim of the ID token is always to be used in the client (aud) in order to be able to use information about the user there, such as abbreviations, first and last names.

DO’s & DON’Ts

  • ❌ ID tokens are not used for authorisation, only for identification and authentication.
  • ❌ ID tokens should not contain any information for authorisation such as roles or similar.
  • ❌ ID tokens should not be sent to an API.

Refresh Token

The Refresh Token is a token that is basically longer valid than the Access Token, and can be used to request a new, valid Access Token.

It is important to note here that the Refresh Token should be used with caution, and should not be valid for too long. Otherwise, a master key is generated that can be used to issue valid access tokens again and again.

Here, OAuth or OIDC offers further security methods, such as token rotation or similar.

DO’s & DON’Ts

  • ❌ Refresh tokens should not be valid for too long.
  • ✅ Refresh tokens must be stored securely.

Endpoints

Authorisation Endpoint

The whole process of authorisation of the client, as well as the authentication of the user is handled via this endpoint. Depending on the flow (more on this later), user interaction is required here.

Token Endpoint

The token endpoint exchanges an OAuth 2.0 grant (e.g. code, refresh token or similar) into an ID and / or access token.

UserInfo Endpoint

The UserInfo Endpoint returns, if a valid Access Token is sent with the request, user information / claims. The previously requested Scopes are returned.

Scopes & Claims

By means of so-called scopes, OAuth can give certain instructions or request data. There are standardised scopes such as OpenID, but it is also possible to define your own scopes.

A scope can consist of a claim. Simply put, a claim is a statement or an assertion that a subject (a user or the authorisation server (IdP)) makes about itself or another subject. Let’s look at an example to make everything clearer:

The Scope profile is standardised and according to the OIDC Spec consists of (among others) the following claims:

  • name: The name of the user in legible form, e.g. Tom Trapp.
  • family_name: The user’s last name, e.g. Trapp.
  • given_name: The first name of the user, e.g. Tom.

Thus, if you request the scope profile, you get back end-user information (claims). These claims are written to the JWT token and can then be retrieved, for example, via the UserInfo endpoint.

Scopes can also be used to request a specific behaviour, for example. For example, the scope openid must always be present if it is an OpenID Connect (OIDC) flow.

It is important to mention that all scopes in the OIDC client must be enabled on the IdP. This allows you to control which client or which Relying Party gets access to which scopes & claims and thus user attributes.

Flows

In the following, we will take a closer look at the different flows in the OpenID Connect context. It is important to mention that for each web application that wants to start an OIDC flow, a registered OIDC client on the IdP is required.

This OIDC client consists (depending on the flow, among other things) of the following information:

  • Client ID: The unique ID of the OIDC client.
  • Client Secret: A unique password for this client ID.
  • Redirect uri: The callback endpoint that will be called with the tokens from the IdP on the Relying Party.
  • Response Types: The type of response the client expects. Classically code for an authorisation code.
  • Scopes: The assertions or permissions that the Relying Party may request.

It is worth mentioning here that the OIDC Flow will fail if, for example, an incorrect redirect URI or an unreleased scope is requested by the Relying Party.

Authorisation Code Flow

For whom? Web applications with their own backend that is not publicly visible (e.g. a server).

An Authorization Code is a very short-lived code, which can be exchanged for an Access Token, an ID-Token and/or a Refresh Token at the Token Endpoint in combination with the client_secret.

OIDC Authorisation Code Flow

Figure: Source: (25.07.2022) https://backstage.forgerock.com/docs/am/7/oidc1-guide/openid-connect-authorization-code-flow.html

Authorization Code Flow with Proof Key for Code Exchange (PKCE).

For whom? For example, a Single Page Application (SPA) without its own backend.

PKCE provides additional security with code_challenge and code_verifier, as the actual client secret cannot be stored securely (as FE application). These two parameters are generated by the Relying Party, stored on the IdP at Request for Authentication and checked again later when the Auth Code is exchanged. This ensures that the issuer is uniquely verified.

OIDC Authorisation Code Flow

Figure: Source: (25.07.2022) https://backstage.forgerock.com/docs/am/7/oidc1-guide/openid-connect-authorization-code-flow-pkce.html

Single Page Application (SPA), which does not require an Access Token.

Very open, little security DO NOT USE!

OIDC Implicit Flow

Figure: Source: (25.07.2022) https://backstage.forgerock.com/docs/am/7/oidc1-guide/openid-connect-implicit-flow.html

Client Credential Flow

For whom? Machine to Machine or Service to Service Communication. This is used when the resource owner is also the client, i.e. the client’s own data is queried.

OIDC Client Credential Flow

Figure: Source: (25.07.2022) https://backstage.forgerock.com/docs/am/7/oauth2-guide/oauth2-client-cred-grant.html

Resource Owner Password Flow

Use with caution! If redirect-based flows (such as Authorization Code Flow) cannot be used. Here the client uses the credentials of the resource owner to get an access token.

This flow is also not recommended and is considered to be the “most insecure OAuth 2.0 flow”.

OIDC Resource Owner Password Flow

Figure: Source: (25.07.2022) https://backstage.forgerock.com/docs/am/7/oauth2-guide/oauth2-ropc-grant.html

Outlook OAuth 2.1

OAuth 2.1 is in the starting blocks and brings some important changes with it! Among other things, the aim is to standardise the OAuth 2.0 RFC jungle again.

The most important changes briefly explained: PKCE (Proof Key for Code Exchange) is now mandatory for the authorisation code flow. Redirect URIs must now be compared with an exact string matching (regex may no longer be used).

  • The Implicit Grant Flow (response_type=token) is completely removed from the spec, this is considered unsafe.
  • Resource Owner Password Credentials Grant Flow is also removed from the spec.
  • Bearer tokens may no longer be included in query string parameters.
  • Refresh tokens for “public” clients are restricted and made more secure.

I hope that I could bring OAuth and OIDC a bit closer to you. Stay tuned for more interesting TechUp’s! 🚀

Tom Trapp

Tom Trapp – Problemlöser, Innovator, Sportler. Am liebsten feilt Tom den ganzen Tag an der moderner Software und legt viel Wert auf objektiv sauberen, leanen Code.