Security
Background
In this library, we’ve chosen to implement OAuth and OpenID flows from the ground up to provide flexibility and meet specific requirements and to be flexible. Not only has every OIDC providr it's own needs, but we also want to stay as close to the standards defined by OpenID Connect and OAuth 2.0 specifications.
However, we strictly avoided writing our own cryptographic functions, instead relying on the well-tested libraries jose for token validation and noble-ciphers for cryptographic operations. Both of which are 0-dependency libraries.
This approach ensures that while we retain control over the authentication flows, we benefit from the security guarantees provided by audited and widely trusted cryptographic implementations, which are essential to avoid vulnerabilities and security flaws.
OAuth 2.0
This module only implements the Authorization Code Flow and optionally the Hybrid Flow in a confidential client scenario as detailed in the OpenID Connect specification.
We will not support the Implicit Flow in the future, as it should not be used anymore and was practically superseded by the Authorization Code Flow.
We will also not support the Client Credential Flow, as it is not part of OIDC, but of OAuth2 and is correctly named Client Credentials Grant. It is basically just an exchange of credentials for a token, is not meant for user authentication and can easily be implemented using a simple fetch request.
Nuxt
This module only works with SSR (server-side rendering) enabled as it uses server API routes. You cannot use this module with nuxt generate or ssr turned off. We are currently investigating if and how to support prerendering.
Session encryption
We store sensitive data, especially the refresh_token, access_token and id_token in an encrypted persistent session object. This library uses the Nitro storage layer to interact with data and uses the oidc namespace.
Here is an example configuration. You can also replace the storage by any supported Nitro storage providers like redis, just keep in mind that the underlying storage has impact on the authentication process duration depending on its latency.
nitro: {
preset: 'node-server',
storage: { // Use local file system storage for dev quick setup
oidc: {
driver: 'fs',
base: 'oidcstorage',
},
},
},
Configure secrets
Nuxt OIDC Auth uses three different secrets to encrypt the user session, the individual auth sessions and the persistent server side token store. You can set them using environment variables or in the .env file.
All of the secrets are auto generated if not set, but should be set manually in production. This is especially important for the session storage, as it won't be accessible anymore if the secret changes, for example, after a server restart.
If a refreshable cookie session still exists but its persistent oidc storage entry is missing (for example after container or storage changes), the module clears the stale session by default and requires a fresh login. You can change this behavior with session.missingPersistentSession (clear, warn, silent).
If you need a reference how you could generate random secrets or keys, we created an example as a starting point: Secrets generation example
- NUXT_OIDC_TOKEN_KEY (random key): This needs to be a random cryptographic AES key in base64. Used to encrypt the server side token store. You can generate a key in JS with
await subtle.exportKey('raw', await subtle.generateKey({ name: 'AES-GCM', length: 256, }, true, ['encrypt', 'decrypt'])). You just have to encode it to base64 afterwards. - NUXT_OIDC_SESSION_SECRET (random string): This should be a at least 48 characters random string. It is used to encrypt the user session.
- NUXT_OIDC_AUTH_SESSION_SECRET (random string): This should be a at least 48 characters random string. It is used to encrypt the individual sessions during OAuth flows.
Add a NUXT_OIDC_SESSION_SECRET env variable with at least 48 characters in the .env file.
# .env
NUXT_OIDC_TOKEN_KEY=base64_encoded_key
NUXT_OIDC_SESSION_SECRET=48_characters_random_string
NUXT_OIDC_AUTH_SESSION_SECRET=48_characters_random_string
Token validation
ID and access token validation involves verifying the integrity and claims of the ID token (usually a JWT) to authenticate the user, and validating the access token by checking its signature, expiration, issuer, and audience to ensure it grants appropriate permissions for resource access. This is critical to prevent token tampering, misuse, and unauthorized access to protected APIs or services.
We use the well-known and tested jose library for JWT validation. Configure provider-level tokenValidationMode: 'strict' to validate every enabled JWT in callback and refresh token responses without trusting its decoded claims first. Strict validation verifies signature, expiration, issuer, and token-specific audience:
- Access tokens use configured
audience. - ID tokens use configured
clientIdand requiresubandiat. Presentazpmust matchclientId, and multi-audience ID tokens require it. Callback ID tokens also require a matching authentication-request nonce when nonce is enabled. Refreshed ID tokens must retain the original ID-token subject and, when present, authentication time.
Strict access-token validation requires audience. Any enabled strict validation requires OpenID discovery metadata containing issuer and jwks_uri. If validateIdToken is enabled, token response must include an ID token.
legacy remains default for current production line. During callbacks, it validates enabled tokens only when decoded aud exactly equals configured audience or client ID, and emits one migration warning per provider when validation is skipped. Refresh responses retain existing parsing behavior. Migrate providers issuing JWTs to strict after configuring required audience and discovery metadata. strict is intended to become default in next explicitly breaking release.Strict refresh validation runs before session or persistent token state is updated. Invalid responses use existing refresh failure handling to clear stale session state.
Some providers, including Auth0 configurations without API audience, may issue opaque access tokens. Preserve support explicitly with validateAccessToken: false and skipAccessTokenParsing: true; ID-token validation can remain enabled independently. tokenValidationMode: 'strict' does not override these opt-outs and validates only token types enabled by their validate*Token flag.
Offline end-to-end tests use the generic oidc fixture with deterministic test-only signing keys, matching discovery and JWKS metadata, and strict access-token and ID-token validation. Integrated coverage exercises login, refresh, logout, and rejection of invalid signatures, issuer or audience mismatches, and nonce mismatches without a live identity provider.

