DEV Community

Cover image for The Best Security for Single Page Applications(SPA) - OpenID Connect OAuth 2.0 Authorization Code PKCE Flow
Kiran Mali
Kiran Mali

Posted on • Edited on

The Best Security for Single Page Applications(SPA) - OpenID Connect OAuth 2.0 Authorization Code PKCE Flow

The user identity and data security is a crucial part of your application. Your application should need to be 100% sure that the one who is using the application is the correct user. The only username/password security to identify users and for application security is a bad idea 👎 .

What is OpenID Connect OAuth 2.0?

🎯 OpenID Connect OAuth 2.0 is the best security framework available nowadays.

You must have seen in so many applications that log in with Twitter, Gmail, Facebook. So Once we click on a button it redirects us to specific social media(OP - OpenID Connect Server). We login to social media, redirect back to the current application and the current application allows us to log in. So How can social media platform allows the other application to authenticate and authorized user so This is OpenID Connect OAuth 2.0 security.

More Details

Instead of building your own just username/password security, you should have to integrate implement or integrate OpenID Connect OAuth 2.0 security.

There are many security flows available in OpenID Connect OAuth 2.0. As per your Application requirements and flow, you can choose the flow.

There are three flow for Single Page Application(SPA).

  1. Implicit flow
  2. Authorization Code Flow (without PKCE) - This is not really for SPA Applications
  3. Authorization Code PKCE Flow

❌ Why not implicit flow?

Because it exposes access_token into the browser URL and you will not have refresh_token facility because OP client is not able to call /token endpoint which requires client authentication.

Below is the implicit flow diagram which helps you to understand the whole flow.

Note: server.com and client.com are just for example. You need to use endpoints as per your OpenID Providers.

Alt Text

❌ Why not Authorization Code Flow (without PKCE) for SPA?

Stop.

Alt Text

Don't use it. Without PKCE that means You need to store the client secret on your browser to request /token endpoint and get an access token. Store client secret at the browser is a big security risk.

This flow is generally used at the server-side. Where we can safely store client id and client secret. In this case, the /token endpoint is protected by Token Endpoint authentication methods. ✔️ You don't need PKCE flow if you are managing authentication flow using the server.

✔️ Why to use Authorization Code PKCE flow.?

❤️ If you have a SPA(Single Page Application), the best security flow for this is the Authorization Code with PKCE flow. Because It does not expose access token to the browser in URL and you don't need client secret at all.

PKCE stands for Proof Key for Code Exchange.

In this case, the /token endpoint is not protected by Token Endpoint authentication methods. Because of PCKE, OP Server use code_challenge and code_verifier to verify request. You also need to check what should be the token endpoint auth method for PKCE flow. This is vary as per oidc service provider.

✔️ Authorization Code PKCE flow and implementation

Alt Text

Note: server.com and client.com are just for example. You need to use endpoints as per your OpenID Connect Providers.

1.First, you need to code_verifier and code_challenge. Below is the code of Node.js to generate code_challenge. code_verifier is just a random string.

var code_verifier="s4vqXQA0ePi98eS9Px4jcghBi7UQHRaQl6jMRwLkBj9Eh8g1yxnesereK4jUHdAT0HkLEWBPLZ8z35HX1Ditxf"

const crypto = require('crypto')
const base64url = require('base64url')

var hash = crypto.createHash('sha256').update(code_verifier).digest();
var code_challenge = base64url.encode(hash)
console.log(code_challenge)
Enter fullscreen mode Exit fullscreen mode

This is a simple Node.js code. For SPA applications, there is the best library available that is AppAuth JS. I've a integrate it with Angular and React Please check links

GitHub logo kdhttps / appauth-angular

Appauth JS integration with Angular 🚀 🛡️

App Auth Angular

App-Auth JS integration with the Angular App. This project was generated with Angular CLI version 8.3.20.

angular-flow

Prerequisites

  1. Node JS >= 10.x.x
  2. @angular/cli >= 8.3.21
  3. Auth0 client - Currently for I am using auth0.com as a OP Server. Demo should work with every OP Provider.

Configuration

Use environment.ts to set OP Client configuration.

Start

  1. Install Dependencies
npm install
  1. Run ng serve for a dev server. Navigate to http://localhost:4200/. The app will automatically reload if you change any of the source files.

GitHub logo kdhttps / appauth-react

Appauth JS integration with React 🎯

App Auth React

App-Auth JS integration with the React App. This project was bootstrapped with Create React App.

react-flow

Prerequisites

  1. Node JS >= 10.x.x
  2. Auth0 client - Currently for I am using auth0.com as a OP Server. Demo should work with every OP Provider.

Configuration

Use environment.js to set OP Client configuration.

Start

  1. Install Dependencies
npm install
  1. Start Application
npm start

Runs the app in the development mode.
Open http://localhost:4200 to view it in the browser.




2.Authorization request to OP Server

HTTP Get redirect

https://server.com/authorize
?redirect_uri=https://client.com/callback
&client_id=[your_client_id]
&response_type=code
&state=[uuid]
&scope=openid%20email%20profile
&code_challenge=[code_challenge]
&code_challenge_method=S256
Enter fullscreen mode Exit fullscreen mode

3.OP Server authenticates the user and redirects back to https://client.com/callback with code in URL. You can check the above flow diagram.

4.Now request to https://server.com/token with code and code_challenge.

HTTP POST https://server.com/token
content-type: application/x-www-form-urlencoded
accept: application/json

Form Data:
grant_type: authorization_code
client_id: [your_client_id]
redirect_uri: [your_callback_url]
code: [code]
code_verifier: [code_verifier]
Enter fullscreen mode Exit fullscreen mode

This request will return your JSON response with access_token

5.Request to https://server.com/usernifo endpoint with access_token and get user info.

I am not forcing you to use PKCE flow but it is better than the implicit flow.

I've integrated the Authorization Code PKCE flow in my Angular and React App. Code links are given below:

GitHub logo kdhttps / appauth-angular

Appauth JS integration with Angular 🚀 🛡️

GitHub logo kdhttps / appauth-react

Appauth JS integration with React 🎯

I've one application on Heroku. If you want to check then click here https://mean-star.herokuapp.com/

I am using auth0.com as my OpenID Connect Server. You can use any provider which provides you OpenID Connect Standards. I would like to list here some: Janssen Project Auth Server, Gluu Server, Auth0, Okta, KeyCloak. Please comment if you have more OpenID Connect Providers

You can also use Google, Twitter, Facebook who provide this feature.

Happy Helping 😊, Thank you !!!

For More Blog

Top comments (3)

Collapse
 
vikashkodati profile image
Vikash Kodati

Nice article Kiran. Suppose PKCE flow is not supported by my home grown IDP, what are the options to securely store the clientsecret? Because my IDP only support OIDC Authcode flow which also needs clientsecret to be passed along

Collapse
 
kdhttps profile image
Kiran Mali

Hello vikash,

Thank you but as far as my knowledge there is no way. You have to use PKCE flow for frontend. As your IDP is not support PKCE that means you have to go with implicit flow and compromise with security.

And sorry for late reply.

Collapse
 
bolilla profile image
Borja Roux

Hi. The client secret will not be a secret, but you can still use it in your home grown IDP. Just be aware it won't provide additional security.

If you don't implement PKCE, you can use either the 'state' OAuth parameter or the 'nonce' OIDC parameter (as discussed here datatracker.ietf.org/doc/html/draf...) for protection against CSRF. It is not the same, but it will improve your security.