Custom claims

Custom Claims can be used to:

  • Pass RBAC information from Member Metadata or Organization Metadata to Sessions.

  • Integrate with third-party providers that support JWT-based authentication, such as Hasura.

If you want to add the same set of custom claims to every Session for your project, Custom Claim Templates may be a good fit.

Using custom claim templates

Custom Claim Template Overview

Custom Claim Templates use a markup language to generate a JSON object using the Member's information.

  • The JSON object output for a particular Member will be used as the initial set of custom claims for all of that Member's Sessions.

  • Claims from templates can still be updated, deleted, or added to by passing in a session_custom_claims argument in an API request.
  • Claims from Custom Claim Templates are subject to the same set of limitations that API-driven custom claims have: the total size cannot exceed 4kb, and no registered claims may be used to ensure interoperability.
  • Updates to the Custom Claim Template or Member Metadata will propagate to existing Sessions the next time a JWT is minted. Previously minted JWTs are immutable and cannot be updated. Clients can force a new JWT to be minted by calling the Authenticate Session endpoint endpoint.

Custom Claim Template Markup Syntax

The Custom Claim Template markup language uses {{ variable }} syntax to denote information that should be passed in at runtime. When dealing with Member or Organization Metadata, use dot notation to access nested fields, e.g. {{ member.trusted_metadata.subscription.level }} will access the level field of the subscription object in trusted_metadata on a Stytch Member object.

Variables can evaluate to any JSON object - strings, numbers, null, objects, or arrays. Variables can only be used as JSON values, and cannot be used as object keys.

If a variable evaluates to null, or attempts to access a value that does not exist, the generated claim will not be present in the output.

Today, the following template variables are supported:

  • {{ member.member_id }}
  • {{ member.name }}
  • {{ member.email_address }}
  • {{ member.trusted_metadata.$PATH }}
  • {{ organization.organization_id }}
  • {{ organization.organization_name }}
  • {{ organization.organization_metadata }}

More variables will be added in the future.

Example

For example, the template:

{
  "https://hasura.io/jwt/claims": {
    "x-hasura-default-role": "reader",
    "x-hasura-allowed-roles": {{ member.trusted_metadata.roles }},
    "x-hasura-user-id": {{ member.member_id }}
  }
}

could be combined with the Member's information:

{
  "member_id": "member-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
  "trusted_metadata": {
    "roles": ["admin", "reader"]
  }
}

to produce the final set of custom claims:

{
  "https://hasura.io/jwt/claims": {
    "x-hasura-default-role": "reader",
    "x-hasura-allowed-roles": ["admin", "reader"],
    "x-hasura-user-id": "member-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6"
  }
}

Adding custom claims to sessions

You can add custom claims to a Stytch session by including the session_custom_claims argument on any authenticate method. This argument takes in an arbitrary JSON object - which may be represented as a map, dictionary, or object depending on your language of choice. Custom claims are persisted on the session object and encoded in the session JWT.

To add or update a key, supply a new value.

# initial claims object {}
stytch.sessions.authenticate(token, custom_claims={"key_1": 1, "key_2": 2})
# current claims object {"key_1": 1, "key_2": 2}
stytch.sessions.authenticate(token, custom_claims={"key_1": 9})
# resulting claims object {"key_1": 9, "key_2": 2}

To delete a key, supply a null value.

# current claims object {"key_1": 1, "key_2": 2}
stytch.sessions.authenticate(token, custom_claims={"key_1": 9})
# resulting claims object {"key_2": 2}

If a value for one of your custom claims is itself a JSON object, you can update and delete values in the same way.

sessions.authenticate(token, custom_claims={
    "b": null,
    "c": 3.5,
    "e": {
        "nested1": "val1",
        "nested2": "val2"
    }
})
# resulting claims object
# {
#    "c": 3.5,
#    "d": 4,
#    "e": {
#        "nested1": "val1",
#        "nested2": "val2"
#    }
# }

stytch.sessions.authenticate(token, custom_claims={
    "e": {
        "nested1": nil,
        "nested3": "val3"
    }
)
# resulting claims object
# {
#     "c": 3.5,
#     "d": 4,
#     "e": {
#         "nested2": "val2",
#         "nested3": "val3"
#     }
# }

Limitations

  • Certain claims are reserved and will result in an error if they are set (iss, sub, aud, exp, nbf, iat, jti, https://stytch.com/*)
  • Total custom claims size cannot exceed four kilobytes.

Any feedback? We'd love to hear it! Reach out to support@stytch.com.