Authorization code grant with PKCE

Recommended

The Authorization Code Flow with PKCE accepts a secret that is created by the application and is verified by the authorization server. This is known as the Code Verifier, and it’s used to create the Code Challenge which is sent over HTTPS to retrieve the authorization code.

For more in-depth implementation details, check out Authentication (Single-page application).
Why do we need to do this?

This is mainly because Native and Single-page apps (SPAs) cannot securely store the Client Secret. However, even server-side apps benefit greatly from this approach.

Fortunately, OAuth 2.0 has a flow for this very situation.

Freepik hacker icon

With this approach, if an attacker somehow intercepts the authorization code, they aren’t able to guess what the code_verifier is since, it is only stored locally by the app and not sent over the network.

With this authentication method, the calling app can proves that it is the legitimate owner of that authorization code, just as a client_secret proves a client is legitimate.

Flow

auth with pkce flow

  1. A user logs in from your app.

  2. Calling application generates the code_verifier

  3. Calling application hashes the code_verifier to create the code_challenge.

  4. ReachFive’s SDK redirects the user to the ReachFive Authorization Server /oauth/authorize endpoint with the code_challenge.

  5. ReachFive’s Authorization Server redirects the user to the login and auth prompt.

  6. The user authenticates through one of the login options.

    Users may see a consent page listing the permissions ReachFive will give to the regular web application.
  7. ReachFive’s Authorization Server stores the code_challenge and redirects the user back to the application with an authorization code.

    This is for one-time use only.
  8. ReachFive’s SDK sends the code as well as the code_verifier to the ReachFive Authorization Server /oauth/token endpoint.

  9. ReachFive’s Authorization Server verifies the code_challenge and code_verifier.

  10. ReachFive’s Authorization Server responds with an ID Token and Access Token.

    This could also be a refresh token.
  11. Your app can then use the Access Token to call the API to access information about the user.

  12. Your API responds with the requested data.

PKCE importance

The PKCE flow is relevant even for server-side integrations where the client_secret is used. Because servers are often stateless, when a server-side app receives an authorization code, it exchanges it at /oauth/token. Using PKCE in server-side apps ensures that only legitimate clients are able to exchange the code.

PKCE flow with confidential clients

It’s important to understand how PKCE interacts with different types of clients and application architectures. While PKCE is essential for public clients like SPAs and mobile apps, its role with confidential clients (such as traditional server-side applications) can be less obvious. Let’s clarify how PKCE works in these scenarios and what you need to consider when integrating it with your application’s authentication flow.

Why enforce PKCE for confidential clients?

Confidential clients receive an authorization code at the redirect_uri, which is opaque and exchanged at /oauth/token with the client_secret. This exchange seems secure since only the client possesses the client_secret, and the code is bound to the redirect_uri. However, the redirect_uri is often predictable, offering limited protection.

RFC 9700, Section 4.5, describes a situation where an attacker tricks a victim into using a malicious link with the attacker’s code, potentially granting limited resource access. To mitigate this, OAuth 2.1 mandates PKCE for confidential clients, binding the authorization code to the end-user’s session, rendering malicious codes unexchangeable as they are tied to the attacker’s device.

In all cases, the backend must be involved in the secure parts of the flow for confidential clients.

Enforcing PKCE on confidential clients

auth with pkce confidential flow

Even if you enforce PKCE for a client, if the client is confidential (uses a client secret, e.g., with "Post" or "Basic" authentication), the SDK will not generate the code_challenge on the frontend. This is because the secure part of the flow (the code exchange) must always be handled by the backend.

The only way to use PKCE with the SDK for confidential clients with ReachFive is to enable the orchestration option.

In this setup:

  1. The backend initiates the flow, generates and stores the code_verifier, and calls /authorize.

  2. ReachFive redirects the browser to the configured Login URL.

  3. The SDK on the frontend automatically detects the orchestration token; no additional work is needed on the frontend.

  4. The authorization server (ReachFive) then handles the code exchange, using the stored code_verifier to create the code_challenge and complete the flow.

This orchestration approach ensures your OAuth/OIDC flow is compliant: every flow starts with /authorize, and the backend manages the sensitive parts.