Increase the security and simplicity of your Information System with OAuth 2.0, OpenID Connect and @axa-fr/react-oidc

Guillaume Chervet
Just-Tech-IT
Published in
11 min readApr 26, 2022

This article aims to introduce what OAuth 2.0 is, then OpenID Connect and finally the @axa-fr/react-oidc library available on GitHub (of which I am one of the repository-maintainers). This article is based on a course on REST APIs available on GitHub that I give at IG2I Lens (school of the Groupe Centrale Lille in France).

You can now play with the demo of @axa-fr/react-oidc, it will probably help you better understand the rest of the article.

Introduction to the demo of @axa-fr/react-oidc and OpenID Connect (OIDC) — YouTube

Introduction

In this article, I will start by explaining some prerequisites, then the OAuth 2.0 protocol, then I will present the advantages of OIDC that build on Oauth 2.0 and complements it. Finally, I will introduce why @axa-fr/react-oidc is a real innovation in terms of security and simplicity.

Preamble

Authentication, identification and authorization management are central and very technical things; often overlooked, they generate enormous additional costs for each application and in the overall management of information systems.

OAuth 2.0 is a protocol for managing permissions. Unfortunately, there are no details on how to implement it technically. As a result, each implementation is different.

OpenID Connect (OIDC) is the next step. It is an identification layer based on the OAuth 2.0 protocol. It normalizes the technical part via a REST API and standardizes the retrieval of credentials.

The result is that the consumer can switch OIDC providers without writing a single piece of code. It also allows you to make OAuth 2.0 compatible with your old authentication systems. It can act as an interface.

Understand the concepts of identification, authorization and authentication

It is necessary to master the distinction between these concepts, because this vocabulary is important to understand the article.

  • Identification : Who are you? Example: Login
    Who can be authenticated? It is often either a person or a machine.
  • Authentication : Are you really that person/machine? Example: Password.
  • Authorization : Does this person/machine have the right to access this resource?

On the HTTP client side, this is transcribed as below

  • Authentication
    Response code HTTP 401, if I am not authenticated and trying to access a private resource
  • Authorization
    Response code HTTP 403, I am authenticated but I do not have the right to access the resource
  • Identification
    It can be carried out in many different ways (form, certificate, validation by an application, etc.).
    If you make an identification via a web form:
    Response code HTTP 400, the information I send by form via HTTP POST is not valid.

OAuth 2 defines 4 distinct roles

  • Resource Owner
    A human or a machine
  • Resource Server
    Hosts data that is protected for access
  • Client Application
    An application requesting data from the resource server.
  • Authorization Server
    Issues access tokens to the client.
OAuth 2 defines 4 distinct roles
OAuth 2 defines 4 distinct roles

Why OAuth 2.O?

Imagine that you start a startup and because you are pragmatic, you realize a “Monolith” well divided into functional areas, domains.

Monolith with multipe domains

Example of functional areas:

  • Order Management
  • Identification, Authentication, Authorization
  • Sending SMS/email
  • Inventory Management, Items
  • Image Management

Super! Your application is successful and is now used by thousands of customers simultaneously around the world. Response times are starting to degrade because your API is under heavy strain.

You went from 2 developers to 45, developments and deliveries become complicated.

You have a new need to open your API to third-party partners!

The solution

To be able to keep acceptable response times and that the application remains maintainable, the application is rearchitected into microservices.

In order to be able to manage authentication on all functional “services”, the first bricks to be extracted are those that manage authentication, identification and authorization.

You must be able to trace everything who/what accesses what at a time T, to control and limit access.

Microservice architecture
Microservice architecture

This protocol allows third-party applications to gain limited access to an exposed service via HTTP through prior authorization from the resource owner.

Castle
Fortified castle

This is the opposite of the fortified castles. It’s hard to get into a castle but once you’re there you do what you want. And that’s not good! This is also why we don’t build castles anymore.

With OAuth 2.0 we start from the opposite principle, that is to say that we know that “yes”, we will be hacked one day. We will be hacked BUT on a very limited resource, and over a very short period of time.

Moreover, in the event of an intrusion, the entities and tokens involved are revocable by the authorization server.

Au revoir

For this OAuth 2.0 is based on a set of two tokens

Access Token

Allows the resource server to allow a user’s data to be made available. This token is sent by the client (application) in the request to the resource server. It has a limited lifetime that is set by the authorization server: for example, 20 minutes.

Refresh Token, the renewal token

This token is issued at the same time as the access token. It is used to renew the access token when it has expired. It has a limited lifespan, but longer than the access token: for example, a week.

Token renewal scheme
Token renewal scheme

Concretely, the “access_token” is the one you send to your API all the time. It is mostly a JSON Web Token (JWT). It is a standard format for exchanging information between clients and servers which makes it sure that the information has not been modified along the way. The “refresh token” is not necessarily a JWT. It transits less on the network but is more sensitive from a security point of view because it allows renewal.

Scopes and Audiences

In the content of the access token and if it is a JSON Web Token (JWT), you will hear about “Scope” and “Audience”. These 2 are very important and quite complex pieces of information to understand.

JWT example of a “access_token” that has the “audience” and the “scope”
JWT example of a “access_token” that has the “audience” and the “scope”

Scope

Used to limit the range of access rights.

The authorization server defines the list of available scopes. The client must send the scope(s) it wishes to use when initializing the identification. A good practice is to request only the scopes useful for the current functionality, and not more. The more you reduce the list of requested scopes, the more you will reduce your attackable surface.

Example: openid email profile account-read account-payment

Audience

Specifies the API(s) you are targeting.
The authorization server defines the list of available audiences.

Example: api-bank api-payment

Warning
Warning

Security: Your “resource” server must always:

  • Control the scopes necessary for each call.
  • Check that the necessary audience is present.

If you don’t, your API can be accessed with any token generated by your authorization server. For example a token generated via another application.

Roles

“Audience” and “Scope” are not roles. The notion of role is yet another thing very specific to each API.

In your API, you must check:
1) that the access token carries the “Audience” that corresponds to you,
2) for each functional part or “resources” in REST terms (because your API can offer several) you check that the “Scope” associated with the functional part of the current HTTP request is indeed present; A Restful API is normally structured in functional domains that are well decoupled from each other.
3) Finally, if you need a finer management of access rights, you check if the user has the right to perform this action using a role (example: user, validator, reviewer, administrator). The notion of role is much finer and is not part of the OAuth 2.0 protocol. It is related only to your application. It is up to you to inject the necessary information, for example, into the key/value fields of the JWT access token from your OIDC server.

For example, adding a “claim” to give the roles of the connected user:
- member_of: user, administrator

Example of adding a “claim” to manage the roles specific to each API
Example of adding a “claim” to manage the roles specific to each API
Focus on the item-stock API of your Information SystemFocus on the item-stock API of your Information System
Focus on the item-stock API of your Information SystemFocus on the item-stock API of your Information System

Be known to the authorization server

A client cannot use the OAuth 2.0 protocol without being known to the authorization server. It must therefore register with the authorization server. For this, it must provide a set of data:

  • App name
  • Website URL in HTTPS
  • Return URL
  • Etc.

In exchange, the server will provide an identifier (“client id”) and, if necessary, a secret code (“client secret”) as strings, which will allow the client to authenticate.

Authorization Types

  • Authorization Code Grant, authorization via a code [Deprecated]
    The client is a web server. Allows you to get a long-term access token that can be renewed via a renewal token.
  • Implicit Grant [Deprecated]
    The application is on the client side (Javascript, mobile application).
  • Authorization Code Flow with Proof Key for Code Exchange (PKCE)
    The application is on the client (Javascript, mobile application) or server side.
  • Client Credentials Grant, server-to-server authorization
    Used by clients to get an access token outside of a user’s context.
  • Resource Owner Password Credentials Grant, authorization via password [Deprecated]

Focus on “Authorization Code Grant with PCKE”

This flow can be used on the client side (a browser or a mobile application, for example) and on the server side.

Client side

Proof Key for Code Exchange: Client Side
Proof Key for Code Exchange: Client Side

This mode is the easiest to set up (and the least expensive), however the access tokens are found on the client side. The client application is therefore very sensitive to “Cross Site Scripting” (XSS) type attacks.

In addition, if a hacker accesses the “refresh tokens”, he can then recover access tokens. Fortunately, you only offer a limited “scope” and “audience” per application!

Server side

Proof Key for Code Exchange : Server Side
Proof Key for Code Exchange : Server Side

This mode is more secure but more complex to set up (more expensive). Today we hear about “Backend For Frontend” (BFF). Access tokens and rollovers are done on the server side (this is authorization delegation). Tokens are normally not accessible from the client (via javascript, in particular).

The session between the client and the server must be done via an exchange of cookies, which must be highly secured because they are also sensitive to XSS type attacks.

« Level up » with OpenID Connect

OpenID Connect (OIDC) adds everything that OAuth 2.0 lacks as standard. With OAuth 2.0, each implementation is different and requires vendor-specific libraries. With OIDC, the implementation becomes simpler.

OpenID Connect standardizes

  • User information retrieval
  • An API (User Info endpoint)
  • Using the ID Token Scope
  • Authentication
  • SSO session management (ex: Single Logout)
  • An OpenID server discovery system, through the use of a “/.well-known” URL; a “/.well-known” URL that lists all other URLs.

All this allows you to change OIDC providers without changing your code

The REST API is simple and standardized:

  • authorization: to authenticate a user
  • token: to request a token (access / refresh / ID)
  • user info: to retrieve user information (identity, rights)
  • revocation: to revoke a token (access / refresh)
  • introspection: to validate a token (access / refresh)

Added a third token: IDToken

The “ID Token” is a JWT that contains the identity of a user.

  • It contains the authentication parameters: expiry date, creation date, authentication date, means to validate the “ID Token” and the “Access Token”.
  • User credentials (roles, authorisations).
  • User attributes (claims) associated with scopes.
    standard attributes:

    - “profile” scope: last name, first name, nickname, date of birth,
    - “email” scope: email, verified email
    - “address” scope: address
    - “phone” scope: phone number, verified phone number
    - etc.
    private attributes:
    - attributes offered by the identity provider. It is necessary to specify them in order to avoid any collision with existing claims.

OpenID Connect lets you federate

Your OpenID Connect server allows you to set up a kind of interface with all your identification, authentication and authorization systems. This makes your old systems compatible with OAuth 2.0, which allows you to make “Single Page Application” (SPA).

An example of an OIDC Server that interfaces between Google, Microsoft and a Custom system, whether you connect to Google or Microsoft or Custom, your client application code will be the same.
An example of an OIDC Server that interfaces between Google, Microsoft and a Custom system, whether you connect to Google or Microsoft or Custom, your client application code will be the same.

It is the OIDC server that manages the complexity and the technical updates with the other systems. Client applications only have to use standard OIDC compatible libraries. A huge gain in simplicity and cost for your Information System!

Finally, let’s talk about AXA React OIDC

React OIDC V4 is a real innovation. It allows you to use the “Authorization Code Grant with PCKE” flow on the client side. This flow is sensitive to XSS type attacks.

The little extra thing that @axa-fr/react-oidc offers is a mode that uses a “ServiceWorker” that acts as a proxy between the client and the server. It allows the “access_token” and “refresh_token” code to be completely hidden from the Javascript client code. The “ServiceWorker” is able to automatically inject your “access_token” in your requests to your API as well as the “refresh_token” in requests to the OIDC server.

react oidc hide and secure tokens from client javascript

Your application therefore becomes much less sensitive to XSS-type attacks and therefore significantly increases its level of security.

This is a real alternative that costs much less to make than setting up a BFF.

The library also allows you to do multiple authentication. This can be practical, in particular for securing certain sensitive operations that require a particular scope or audience. You may not even request a renewal token.

For example when you connect to your bank’s site you can see the balance of your bank account. When you want to make a money transfer, the site will ask you again to authenticate yourself (an over-authentication). In this case, you receive a new scope and/or more sensitive audience valid for a very short period of time and without a renewal token.

For more information, visit the React OIDC Github page.

To summarize, you can finely and permanently give limited access for a limited period.

The future in vanillajs

The library behind @axa-fr/react-oidc is native javascript, so it is not linked to React, there is just a “binding” with React. There is a good chance of seeing new bindings appear very quickly. For example: webcomponent, angular, vuejs, blazor, etc.

Conclusion

You now have an overview of what OpenID Connect is and the keys to simply secure your Information System.

Security is not negotiable, it must be present by default in your applications AND precisely, this is what the tools presented in this article allow you! So what are you waiting for?

A big thank you to AXA France which accompanies me and pushes me to give lessons as well as to do Open Source.

Many thanks to everyone who helped proofread this article:
- Gilles Cruchon
- Lilian Delouvy
- Francois Descamps
- Antoine Blancke
- Louise Ryckewaert
- Preclin Amaury

--

--

Guillaume Chervet
Just-Tech-IT

Esprit créatif, je suis passionné par les technologies, le design et l'ergonomie, ce sont des « outils » qui permettent d'arriver aux résultats.