Using Custom Claims

Descope stores custom claims in the refresh token on the client side. You can add custom claims to your JWTs by adding the Custom Claims action in your flow, or by using a JWT Template.

Descope custom claims within JWT

When using custom claims however, it's important to understand all of the functionalities inherent in them, as well as how to use them securely and responsibly. This guide will focus on all of the different security aspects of custom claims, as well as recommended best practices to employ when using them.

Descope stores your custom claims in the refresh token. In order to properly store your refresh tokens, we typically suggest storing them in a samesite=strict, httpOnly=true, secure cookie.

Since cookies have a maximum size of 4kb supported by browsers, storing information in a custom claim while using cookies (the recommended way) might be a problem. Therefore, it's best to not store too much in the JWT to make sure you don't run into any storage limitation issues.

Do Not Store Sensistive Information

You should never store any sensitive user information in a JWT. This can be sensitive user PII, or other secrets related to your application or authentication architecture. JWTs are just Base 64 encoded tokens, and even if they are stored securely, that sensitive information could be exposed if your JWT was ever compromised by a malicious hacker.

Secure vs Non-Secured Custom Claims

The backend cannot trust custom claims specified by the client SDK or API due to the following items:

  • Potential tampering and spoofing by malicious hackers
  • The lack of a verification mechanism for client-added claims
  • The violation of defined trust boundaries which treat client data as untrusted
  • Inconsistent enforcement policies on accepted claims
  • The foundational security principle that cautions against trusting user input.

With this security in mind, custom claims added by the client SDK will be within the nsec claim in the session token JWT.

When utilizing the management SDK or Descope flows, custom claims that are added will be marked secure, and will not be within the nsec claim.

Below is an example of a session JWT with custom claims added under the nsec claim since they were added by the client.

{
  "amr": [
    "email"
  ],
  "drn": "DS",
  "exp": 1692304651,
  "iat": 1692304051,
  "iss": "P2RFvFexVaxxNFK6rhP0ePtaGfTK",
  "nsec": {
    "email": "example@email.com",
    "name": "Joe Person"
  }
  "sub": "U2RG6grrbT3REKYqk5yC4SjkMqzA",
  "tenants": {
    "T2U7vUH1NPy4JzWHruoOVIGyzYlu": {
      "permissions": [
        "AppSecEngineer",
        "Marketing",
        "Support"
      ],
      "roles": [
        "Engineering",
        "Product Manager"
      ]
    },
    "T2U7vVBqyZv6HdGtGLdnkgCbNxrC": {
      "permissions": [
        "AppSecEngineer",
        "Support"
      ],
      "roles": [
        "Support"
      ]
    }
  }
}

Using the Audience (aud) Claim

The aud (Audience) claim in a JWT specifies the intended recipients of the token, ensuring the correct application or server uses it. It can be a single entity or multiple entities, defined as a string or an array of strings, to prevent the token from being accepted by unintended parties.

Descope allows you to append to the aud claim by utilizing the Custom Claims action to append an item. Below is an example of appending to the aud claim using the Descope custom claims action.

Descope custom claims management add to flow

The returned JWT would look similar to the below.

Terminal
{
  "amr": [
    "oauth"
  ],
  "aud": [
    "xxxx",
    "something"
  ],
  "drn": "DS",
  "eml": "xxxx",
  "enabled": true,
  "exp": 1709674989,
  "iat": 1709674809,
  "iss": "xxxx",
  "name": "xxxx",
  "rexp": "2024-04-02T21:40:09Z",
  "sub": "xxxx",
  "tenants": {
    "xxxx": {}
  }
}
Was this helpful?

On this page