Integrating Single Sign-On with OAuth 2.0 PKCE Flow

Fatih Sinan Yaman
MobileAction Technology
6 min readAug 21, 2023
https://www.freepik.com/free-ai-image/security-system-locks-data-computer-safety-generated-by-ai_41572667.htm#fromView=search&term=login+security&page=1&position=2

Introduction

Single Sign-On (SSO) is a way for users to log into multiple services with just one set of credentials. Having a smooth and secure user experience is crucial and makes a significant difference.

Especially in large companies with many employees, SSO greatly simplifies the task of managing and granting access rights. It reduces the complexities of user management and ensures that the right people have the right access at the right time.

What is PKCE?

PKCE (pixie), or “Proof Key for Code Exchange”, is a security measure introduced to enhance the protection of SSO systems. At its core, PKCE provides an extra layer of security by introducing a unique, one-time code known as the “code challenge”. This ensures that even if an attacker intercepts our temporary authorization code, they can’t misuse it without the original challenge.

Initially designed for mobile apps due to their inability to securely store client secrets, PKCE later found its importance for all OAuth clients. It effectively guards against unauthorized code use. While some might mistakenly consider PKCE a replacement for client secrets, it is, in fact, a complementary security layer. This means it remains advantageous even for applications that have a client secret, fortifying them against potential threats.

PKCE flow diagram

Beneath the PKCE mechanism lie two critical components: the code_challenge and the code_verifier. Let's break down how they work in tandem with the flow diagram above:

  1. code_verifier: This is a random set of letters and numbers created by the client. It is like a secret password.
  2. code_challenge: The client transforms the code_verifier using a specific method to produce the code_challenge. The widely accepted method for this transformation is sha256. Once created, the code_challenge is sent to the authorization server during the initial request.
  3. SHA256: This is a cryptographic hash function, part of the SHA-2 family. By using sha256, the client ensures that the code_challenge sent to the server is a secure version of the original code_verifier.

The clever thing is that the real code_verifier (our original secret password) is never directly shared. Later, when the client asks for a token to enter, it shares this original secret with the server. The server checks it by comparing it with the code_challenge it got before. This way, only the correct client can get access.

PKCE Flow

1- Login Initialization

The user clicks the login button. In the background, the app generates a long random string called the code_verifier. This is like a secret password that only the app knows. Then, the app makes a scrambled version of this, called the code_challenge

2- Login to the Identity Provider

The application now reroutes the user to IDP’s login page (This could be OneLogin or Okta). The user enters their username and password to log in to IDP.

Login to Identity Provider

3- Credential Verification

Upon successful verification, the identity provider acknowledges the code_challenge provided by the application earlier.

4- Return with Authorization Code

The user is then redirected back to the originating application. During this phase, the identity provider hands the application a special ‘authorization code’, a crucial component of this secure flow.

5- Code Exchange at the IDP Server

The application communicates with the identity provider’s server, presenting the ‘authorization code’ alongside the initially generated code_verifier. The IDP server validates whether the code_verifier, when processed, matches the code_challenge received initially.

6- Access Token Procurement

Upon successful validation, the IDP server issues tokens to the application. This often includes an access token, which grants the user access. Depending on IDP settings, it might also provide an ID token, which the application can use to identify which user has logged in, and a refresh token, which can be used to obtain a new access token once the original has expired or been revoked.

7- Token Verification

Importantly, the integrity of this access token can be independently verified by the application’s server, ensuring its authenticity. The commendable aspect of the PKCE method lies in its ability to authenticate securely without the application storing any sensitive client secrets, bolstering overall security.

Integration

Incorporating Single Sign-On (SSO) with PKCE in applications is streamlined thanks to packages like js-pkce. The package offers a set of tools that manage the creation and validation of the required PKCE parameters, thus facilitating the integration process.

1- Create New PKCE Instance:

import PKCE from 'js-pkce';

const pkce = new PKCE({
client_id: 'CLIENT_ID_FROM_IDP',
redirect_uri: 'http://localhost:8080/auth',
authorization_endpoint: 'https://authserver.com/oauth/authorize',
token_endpoint: 'https://authserver.com/oauth/token',
requested_scopes: 'openid',
});

2- Redirect the user to the login page of IDP to login

window.location.replace(pkce.authorizeUrl());

3- Trade the auth-code for a token

const url = window.location.href;
pkce.exchangeForAccessToken(url).then((resp) => {
const accessToken = resp.access_token;
const idToken= resp.id_token;
// Do stuff with the tokens.
});

Advantages of PKCE

1- No Need for Private Information (Client Secret, Keys, Certificates, etc.)

In traditional OAuth flows, applications store a “client secret” for added security. However, on platforms like mobile devices or web browsers, keeping this secret can be risky because it might be exposed to threats. PKCE eliminates the need for such a secret, which is a major benefit for these platforms.

2- Automatic Attack Detection

PKCE introduces specific values like code_verifier which are used during the authentication process. If an attacker tries to misuse an authorization code and they don't have the corresponding code_verifier, the IDP server will recognize this mismatch. This way, any unauthorized attempts can be quickly detected and stopped.

3- Optional Backend Requirement

With PKCE, applications have the flexibility to authenticate users without necessarily having a backend server. This means developers can directly obtain user credentials without the need for server-side processing. This is especially beneficial for lightweight applications.

4- Simplified Integration for Multi-Tenant and Multi-IDP Configurations

If you’re integrating multiple Identity Providers (IDPs) into your application or operating in a multi-tenant mode where each tenant requires its own SSO integration, the PKCE approach simplifies this. For each integration, you only need to specify the Client ID and the . Well-Known JSON URL.

Disadvantages of PKCE

1- Content Security Policy Restrictions

If a system is using a Content Security Policy (CSP), permissions need to be given explicitly for each Identity Provider (IDP). This means that integrating multiple IDPs can complicate CSP management and require more frequent updates.

2- Complexity

Incorporating PKCE adds some complexity to the initial OAuth 2.0 setup. Developers need to understand the new parameters like code_verifier and code_challenge, and how they interact in the flow.

3- Potential Integration Issues

Not all OAuth 2.0 providers may support PKCE out of the box. While its adoption is growing, developers might face challenges integrating PKCE with certain older systems or providers.

Summary

PKCE, introduced in 2015, is a newer security measure designed to enhance the safety of the OAuth 2.0 protocol’s Authorization Code flow. PKCE’s main strength lies in its ability to prevent unauthorized code use. Utilizing elements like the code_verifier and code_challenge, ensures a secure and robust authentication process.

With PKCE is that there’s no need to store any confidential information, such as secret keys. This means the IDP (Identity Provider) takes on almost all of the security concerns. In conclusion, PKCE is a method that balances both security and flexibility.

References:

--

--