SPA and Rest API Application friendly Oauth 2.0/Oidc login flow

In this story, we are going to discuss about the standard Oauth 2.0/Oidc Auth Code flow, the recent Public Client Auth Code flow and finally an improvised version of Auth code flow that’s suitable for SPA and Rest API design applications

Standard Auth Code Flow

Below illustrates sequence diagram of Oauth 2.0 Auth Code flow using PKCE as a replacement of nonce

The behaviours and characteristics

  • Authorization flow are backend driven
  • Uses web session and cookie to keep Oauth 2.0 state
  • Supports offline_access scope, refresh token can be granted at the end of the authentication.
  • Good for information hiding: IdP access token/refresh token are encapsulated from the Application End

The bad

As the Standard Auth Code Flow is designed for Web Application based system back in the days, it is not suitable for modern web framework especially with the Single Page Application + Rest API

  • The design almost limits to cookie authentication (user application session is kept in cookie) and requires Application Frontend to share the same domain as the Backend.
  • Session and cookies are usually be avoided with Rest API with microservice design. But the Oauth 2.0 Auth Code Flow requires it for state validation.

Public Client Auth Code Flow (PKCE flow)

Introduced recently to replace implicit grant that caters for applications that has no backend services such as Single Page and Native/Mobile application.

The behaviours and characteristics

  • Authorization flow are front end driven
  • Uses local storage to keep Oauth 2.0 state
  • As the name goes [Public Client], it has no client secret
  • offline_access scope is commonly not supported, only access token can be granted at the end of the authentication ( vary per IdP )

The bad

  • Less practical, it is unlikely that one will have an application setup without backend, leaving open design upon access token retrieval
  • In the absence of refresh token, the Public Client Auth Code flow relies on the IdP’s session to maintain continuity via silent authentication. This additional coupling might not be favourable in some of the application setup.
  • Less secured, as most of the information can be gathered from the front end.

The Improvised version — Frontend Driven Auth Code Flow

A design that takes the good from both designs

  • The offline_access and the information hiding from Standard Auth Code flow
  • Using browser/client app to manage Oauth 2.0 state validation from Public Auth Code flow

Advantages

  • User session object ( application’s access token and refresh token ) is retrieved in XHR call (Response Payload). Application is free to decide where to keep the user session object (E.g. Local Storage)
  • Supports different origins for frontend and backend, such as cdn.app.com and app.com
  • Seamless integration to header authentication for REST API
  • One size fit all. The design is also applicable to Native/Mobile application as well, in a more secured/encapsulated manner.

Remarks

  • It is advisable not to use IdP’s access and refresh token directly as the application user session object. As stated in the diagram (highlighted in blue), the application generates its own pair of access and refresh token (jwt based) and co-relate the application refresh token with the IdP refresh token. This will allow the refresh token of IdP token on am application refresh token action. This is useful in order to get user latest information from IdP.

Proof of Concept / Reference Implementation

  • Vue.js (FE) and Node.js (BE)
  • Based on oidc-client-js library and openid-client node package library
  • integrated to passport.js library
  • The github repo (here)