Getting Started

Security

Security is a main priority

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.

nuxt.config.ts
  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 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 token validation. Tokens will only be validated if the clientId or the optional audience (aud) field is part of the access_token (or id_token if existent) audiences.

Even if validateAccessToken or validateIdToken is set, but the audience doesn't match, the token should not and will not be validated.

Some providers like Entra or Zitadel don't or just in certain cases provide a parsable JWT access token. Validation will fail for these and should be disable, even if the audience is set.


Copyright © 2024