PKCE flow - Idura Verify Documentation
  1. Verify
  2. Reference
  3. Authorization flows
  4. PKCE flow

Protocol overview

PKCE (Proof Key for Code Exchange) allows you to securely perform a code-for-token exchange without a static client secret. Instead, the client application dynamically generates a unique, one-time secret (a code_verifier) for every authentication request.

Because it protects against code interception attacks, PKCE is the industry-recommended standard for all application types, including traditional server-side web apps, single-page applications (SPAs), and native mobile apps.

@criipto/auth-js and @criipto/verify-react support PKCE.

PKCE flow diagram

Step 1: Build authorize URL

Before making the authorization request, your application must generate the secrets in the format specified in RFC 7636:

  1. code_verifier: A cryptographically random string between 43 and 128 characters long.
  2. code_challenge: A base64url-encoded SHA-256 hash of the code_verifier.

Similar to the standard Authorization Code flow, you start by redirecting the user to the OAuth2 authorization endpoint (/oauth2/authorize), including the code_challenge, code_challenge_method=S256, and the rest of the parameters you would normally include in an authorization request.

Example request

GET https://YOUR_SUBDOMAIN.idura.broker/oauth2/authorize?
    response_type=code&
    response_mode=query&
    client_id=CLIENT_ID&
    redirect_uri=YOUR_REDIRECT_URL&
    acr_values=CHOSEN_IDENTITY_SERVICE&
    scope=openid&
    state=YOUR_STATE&
    code_challenge=YOUR_CODE_CHALLENGE&
    code_challenge_method=S256
  • response_type=code: Indicates that you are using the Authorization Code flow and that you want to receive an authorization code in the response.
  • response_mode=query: Indicates that the authorization code should be returned in the query string of your redirect URI.
  • client_id: The client ID of your Idura Verify application.
  • redirect_uri: The URL to which the user will be redirected after authentication. This must match one of the redirect URIs registered for your application in your Idura Dashboard.
  • acr_values: The specific eID method you want to trigger, e.g. urn:grn:authn:dk:mitid:substantial for Danish MitID.
  • scope: The scopes you want to request. Must always include openid, and can include additional scopes depending on the user data you want to receive in the token.
  • state: A random alphanumeric string you generate. This exact value will be returned in the response and can be used to verify that the response corresponds to the request you sent, protecting your app from cross-site request forgery (CSRF) attacks.
  • code_challenge: A SHA-256 hash of your dynamically generated code_verifier.
  • code_challenge_method=S256: Indicates that you are using the SHA-256 method to generate the code_challenge.

Use our Authorize URL Builder to generate authorize URLs with various parameters. A full reference of all available parameters can be found in the authorization request parameters reference.

Example response

You will receive an HTTP 302 response, which redirects your browser to your specified redirect_uri with the authorization code included in the query parameters:

HTTP/1.1 302 Found
Location: YOUR_REDIRECT_URL?code=AUTHORIZATION_CODE&state=YOUR_STATE

If the authentication request fails, the redirect will include an error code instead:

HTTP/1.1 302 Found
Location: YOUR_REDIRECT_URL?error=ERROR_CODE&error_description=...&state=YOUR_STATE

Step 2: Exchange the code for token

Next, you must exchange the returned code for an actual token. The same as with the standard Authorization Code flow, this is done by posting the authorization code received from the previous step to the token endpoint (/oauth2/token).

The difference is that the static client secret is not included in this request. Instead, you include a code_verifier, which was generated in the previous step.

HTTP POST https://YOUR_SUBDOMAIN.idura.broker/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&
code=AUTHORIZATION_CODE&
client_id=CLIENT_ID&
redirect_uri=YOUR_REDIRECT_URL&
code_verifier=YOUR_CODE_VERIFIER

Example response

A successful request to the token endpoint will return an HTTP 200 OK along with a JSON payload with your tokens. The id_token contains the authenticated user's identity information.

HTTP/1.1 200 OK
Content-Type: application/json

{
  "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjgyN0Q5QTNFOTg2MTY0OTVBQzZGRTE3MUFFNkRBM0IzQ0ExNDE5MjEifQ.eyJpc3MiOiJodHRwczovL25hdGFsaWEtZGV2LXRlc3QuY3JpaXB0by5pbyIsImF1ZCI6InVybjpjaWJhIiwiaWRlbnRpdHlzY2hlbWUiOiJzZWJhbmtpZCIsImF1dGhlbnRpY2F0aW9udHlwZSI6InVybjpncm46YXV0aG46c2U6YmFua2lkIiwiYXV0aGVudGljYXRpb25tZXRob2QiOiJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpTb2Z0d2FyZVBLSSIsImF1dGhlbnRpY2F0aW9uaW5zdGFudCI6IjIwMjQtMDUtMjJUMTA6NDE6NDEuMzYxWiIsIm5hbWVpZGVudGlmaWVyIjoiYmI5YzIzNjRkZmFlNDRmM2JjZmQ5OTkwNTNkOTRmOWUiLCJzdWIiOiJ7YmI5YzIzNjQtZGZhZS00NGYzLWJjZmQtOTk5MDUzZDk0ZjllfSIsInNlc3Npb25pbmRleCI6ImI2NWYxMWI2LWViYTctNDg4Mi05MDBhLTVmMmQ5M2EzOGRiYSIsInNzbiI6IjE5NjgwMjAyMDU3NSIsIm5hbWUiOiJUZXJuZSBQYXVsc2VuIiwiZ2l2ZW5uYW1lIjoiVGVybmUiLCJnaXZlbl9uYW1lIjoiVGVybmUiLCJzdXJuYW1lIjoiUGF1bHNlbiIsImZhbWlseV9uYW1lIjoiUGF1bHNlbiIsImlwYWRkcmVzcyI6IjE4NS4xNTcuMTM0LjEzNCIsImNvdW50cnkiOiJTRSIsImlhdCI6MTcxNjM3NDUwMSwibmJmIjoxNzE2Mzc0NTAxLCJleHAiOjE3MTYzNzU3MDF9.RVQnlukfoH597uXzE1Gays5DElGzAr8xgOmi7ZWppaL3QPGhV4vK2o6qLhxXg_-FKG9xCwHR6gEhnNzWA3W3B6Q2zJeQTYh9okUvTmmhAFIyDL7lEtfWVVKUKvauDisYVZDjAxJQS_1zbgPEi5I-UJ6_kvMGH-wC13MAD2bZGTGR2dR-ZevBUn7plOt0PKXrIZD3vwxDfebTMPQqX_9SNT5F7GLjCcpeVK-T5LOgmUMFcTAbHvNyklqP5ymRHsZLDw_ib4I7ZqODhR-3uISWo1NvG4Y84iBcqv50WRNlmMUm004LfPw1flM5DNsVyUWCqYW8m7eBEwLp5va-6OQG4w",
  "access_token": "cf1ce646-7fbe-4740-9c56-fe3f0891f6c6",
  "token_type": "N_A",
}

Step 3: Validate the JWT

You can now proceed to validating the ID Token Idura Verify returned in response and access the end-user information it contains. The validation step is required: without it, you cannot trust the contained end-user information.

Idura provides a list of integrations that handle most of the authentication process, including JWT validation. Alternatively, we strongly recommend that you find a battle-hardened library for your specific platform to do this heavy lifting. You can find an extensive list of libraries on jwt.io.

For more information, see OpenID Connect security best practices and JWT validation guide.