Authorization Basics

4 mins read

Proof Key of Code Exchange (PKCE)

Learn what the Proof Key of Code Exchange is and what its process is. Find out which applications can use the authorization code grant flow with PKCE safely and securely.

What Proof Key of Code Exchange (PKCE) Is

The Proof Key of Code Exchange (PKCE) is an extension of the standard authorization code grant OAuth flow. It is designed to be a secure substitute for the implicit flow for single-page applications (SPA) or native applications.

SPAs and native applications are vulnerable to reverse engineering practices. For SPAs, the source code of the application is available within browsers. Native apps can be decompiled. Because of those reasons, SPAs and native applications cannot securely store their client credentials (especially client secrets) and are considered public clients.

Authorization code grant with PKCE introduces a technique to prevent unauthorized access to resources in the case of code interception.

Try it now

Cloudentity comes with multi-tenant authorization server as a service that supports both the authorization code flow and the Proof Key of Code Exchange (PKCE) extension.

How PKCE Works

For proper and secure flow of authorization code grant with PKCE, the following is recommended:

  • Configure the redirection endpoint for the client application before making calls.

  • Limit the scope the client application can access when calling the /authorize and /token endpoints.

[mermaid-begin]
sequenceDiagram autoNumber participant User participant Client application participant Authorization server participant Resource server (API) activate User User->>Client application: Access activate Client application Client application->>Client application: Generate code_verifier and transform it to code_challenge activate Authorization server Client application->>Authorization server: Authorization code request + code_challenge to /authorize deactivate Client application Authorization server->>User:Display consent User->>Authorization server: Authenticate and give consent deactivate User Authorization server->>Client application: Issue authorization code activate Client application Client application->>Authorization server: Authorization code + code_verifier to /token Authorization server->>Authorization server: Verify the authorization code, code_verifier, and code_challenge Authorization server->>Client application: Return token deactivate Authorization server Client application->>Resource server (API): Call API with token activate Resource server (API) Resource server (API)->>Client application: Return data deactivate Resource server (API) deactivate Client application

The example diagram above illustrates the interactions that occur during the OAuth authorization code grant flow with PKCE.

  1. A user tries to access the client application.

  2. The client application generates code_verifier and transforms it into code_challenge.

    • code_verifier is a random key that prevents the authorization code from being intercepted. code_verifier is generated by the client application for every authorization request and transformed into code_challenge according to the code_challenge_method set for the client application in advance. It’s mandatory to set the code_challenge_method value to S256, where possible.
  3. The client application calls the authorization server’s authorize endpoint and sends the code challenge along with the authorization request.

    • At least one redirection URI must be configured for the client application. When the application features several redirection URIs, the request to the authorize endpoint must always include the redirect_uri parameter.

    Sample call to the authorize endpoint with Cloudentity as an authorization server

    curl --location \
    --get \
    --url "https://$TENANT_ID.$REGION_ID.authz.cloudentity.io/$TENANT_ID/$WORKSPACE_ID/oauth2/authorize" \
    --data-urlencode "response_type=code" \
    --data-urlencode "redirect_uri=$REDIRECT_URI" \
    --data-urlencode "client_id=$CLIENT_ID" \
    --data-urlencode "code_challenge=$CODE_CHALLENGE" \
    --data-urlencode "code_challenge_method=$CODE_CHALLENGE_METHOD"
    

    Region identifier

    REGION_ID is available for recently created tenants in the tenant URL next to TENANT_ID. The region IDs are assigned as follows:

    • Australia: au

    • Europe: eu

    • USA: us

    For tenants without the region identifier, the REGION_ID parameter must be skipped.

    • Along with the request, the client application sends code_challenge and code_challenge_method.
  4. The authorization server responds with the redirect URI. The user gets redirected to the consent form, if any.

  5. The user authenticates with their identity source and gives their consent.

  6. The authorization server issues an authorization code.

  7. The client application requests authentication to the token endpoint using the authorization code provided in the previous step.

    • The requests to the authorization server must also include the code_challenge with value equal to that sent in the request to the authorize endpoint. This is one of the mandatory requirements of a successful token issue.

    Sample call to the token endpoint with Cloudentity as an authorization server

    curl --request POST \
    --url "https://$TENANT_ID.$REGION_ID.authz.cloudentity.io/$TENANT_ID/$WORKSPACE_ID/oauth2/token" \
    --data-raw "authorization_code=$CODE&code_verifier=$CODE_VERIFIER"
    
  8. The authorization server validates the authorization code, code_verifier, and code_challenge.

    Upon the following:

    • The authorization code is valid

    AND

    • The code_verifier and code_challenge values sent in steps 3 and 7 are equal (pairwise), then
  9. The authorization server returns the token.

  10. The client application requests protected resources from the resource server and submits the token it received in the previous step.

  11. The resource server validates the token and responds with the requested resources.

Cloudentity Auth JS

Cloudentity-auth-js is a library that provides you with a client that makes it possible for JavaScript single-page applications to use the authorization code grant flow with PKCE. To make use of the library, see the cloudentity-auth-js library dedicated GitHub repository.

Updated: Sep 8, 2023