Mitigate Replay Attacks When Using the Implicit Flow

To mitigate replay attacks in the Implicit Flow with Form Post, applications must use a nonce as outlined by the OpenID Connect (OIDC) specification.

The nonce is generated by the application, sent as a query string parameter in the authentication request, and included in the ID Token response from Login 3.0. This enables the application to verify the correlation between the authentication request and the ID Token response.

For details on where to include the nonce, refer to Implementing Login with Implicit Flow in Login 3.0.


Generate a Cryptographically Random Nonce

To generate a secure nonce, you can use tools like Nano ID or the Web Crypto API provided by modern browsers. Here’s an example using the Web Crypto API:

function randomString(length) {
    const charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz+/';
    let result = '';

    while (length > 0) {
        const bytes = new Uint8Array(16);
        const random = window.crypto.getRandomValues(bytes);

        random.forEach((c) => {
            if (length === 0) return;
            if (c < charset.length) {
                result += charset[c];
                length--;
            }
        });
    }
    return result;
}

Persist Nonces Across Requests

The generated nonce must be stored securely in your application for later validation. You can use one of the following methods:

  • HttpOnly Session Cookies (recommended for server-side apps).

  • HTML5 Local Storage (for client-side apps).

For example:

window.localStorage.setItem('nonce', randomString(16));

Validate the ID Token

After Login 3.0 responds with an ID Token, validate and decode the token as usual. Ensure that the nonce claim in the token matches the value sent in the original request. If the nonce doesn’t match, reject the authentication response to prevent potential token replay attacks.

const jwt = '...'; // Decoded ID Token body
if (jwt.nonce === window.localStorage.getItem('nonce')) {
    // Nonce is valid
} else {
    // Nonce is invalid! Potential token replay attack
}

Last updated

Was this helpful?