Skip to content

Authorization code with PKCE

The Authorization Code with Proof Key for Code Exchange (PKCE) flow is an extension of the Authorization Code grant flow. However, with PKCE, requests do not need to include the client_secret in the /token request. The PKCE flow reduces security risks for desktop and mobile applications because the client_secret does not need to be embedded in source code.

Authorization Code with PKCE was designed for desktop and mobile apps, but it can be used in web apps.

How it works

  1. Code_verifier and code_challenge are generated.
  2. Code_challenge is submitted to /authorize endpoint.
  3. The authorization server returns an authorization_code.
  4. Code_verifier and authorization_code are submitted to /token endpoint.
  5. The server responds with an OAuth_code, id_token, and an access_token.
  6. The Access Token is used to authorize the application.

The following is a diagram that shows the Authorization Code with PKCE flow:

Generate a code verifier and challenge code

The first step is the generation of a new code verifier and code challenge. This step is repeated for every authorization request.

Code verifier

The code verifier string must meet the following requirements:

  • Include only the following characters: A-Z, a-z, 0-9, punctuation characters ._- or ~ (hyphen, period, underscore, and tilde.)
  • The verifier string must be between 43 and 128 characters long.

Example in Python

import base64
import os
import re
def generate_code_verifier(code_length):
   code_verifier = base64.urlsafe_b64encode(os.urandom(code_length)).decode('utf-8')
   code_verifier = re.sub('[^a-zA-Z0-9]+', '', code_verifier)
   return code_verifier

Challenge code

The challenge code is a BASE64-URL-encoded string of the SHA256 hash of the code verifier.

Example in Python

import hashlib
import base64
def to_pkce_challenge(code_verifier):
    code_challenge = hashlib.sha256(code_verifier.encode('utf-8')).digest()
    code_challenge = base64.urlsafe_b64encode(code_challenge).decode('utf-8')
    return code_challenge.replace('=', '')

Authorization request

After generating the challenge code, it must be submitted to the authorization server in a GET request. The code generated is valid for 10 minutes.

  • API CALL:

    • GET {baseURL}/oauth/authorize
  • PARAMETERS:

    • client_id = Application ID registered for the application (UUID)
    • response_type = code
    • scope = openid and applicationname (Scope is space delimited)
    • redirect_uri = {Redirect URL registered with Identity}
    • code_challenge = {Challenge Code}
    • code_challenge_method = {S256}
    • state = {string} (This value is optional)
    • ui_locales = {String locale value. This specifies locale language Identity v4 UI will display. This value is optional.}

If the exact locale is unavailable, the display will fall back to the locale base language before reverting to the user’s browser preference.

  • prompt = {Details for each value below. This value is Optional.}

    • none = Trimble Identity will not display any UI, if there is no SSO session the /authorize call will redirect to the caller with a error e.g. /callback?error=login_required&error_description=Authentication%20required
    • login - Trimble Identity will always display the sign in UI, regardless of whether an SSO session exists.
    • create = Trimble Identity will display the sign up page rather than the sign in page.
  • login_hint - {String. Allows an application to specify the email address for use in the sign in or sign up page if you are using prompt=create. This value is optional.}

  • Identity_provider - {Allows an application to declare a specific federated identity provider should be used to authenticate e.g. okta_trimble. This value is optional. For more information on federation, refer to the Federations page.}

The response should give you the authorization_code you need to send to the server with the code_verifier value.

{redirect_uri}?code={authorization_code}&state=test

Example request

https://stage.id.trimblecloud.com/oauth/authorize?client_id={client_id}&response_type=code&scope=openid processing&redirect_uri=https://trimble.com&state=test&code_challenge=1234ABCD5&code_challenge_method=S256

Example response

https://stage.id.trimblecloud.com/oauth/authorize?code=1a44a0...&state=test

Token request

Authorization Server responds with an ID Token and Access Token (and optionally, a Refresh Token).

  • API CALL:

    • POST {``baseURL``}/oauth/token
  • Header

    • Content-Type: application/x-www-form-urlencoded
  • Parameters

    • grant_type = authorization_code
    • code = {code from /auth call}
    • redirect_uri = {redirect_uri}
    • client_id = {Application ID (UUID)}
    • code_verifier = {code_verifier}

Example request:

grant_type=authorization_code&client_id={client_id}&code={code}&redirect_uri={redirect_uri}&code_verifier={code_verifier}

Example response:

{
"access_token": "eyJ0e...",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "VQBrv..."
}
  • To decode and verify the TID JWT Token, refer to Decode JWT