What is a JWT?
A JWT is a string that consists of three parts separated by dots (.):
- Header: Contains metadata about the token, such as the signing algorithm
- Payload: Contains the claims (data) about the user or entity
- Signature: Used to verify the token’s authenticity
header.payload.signature
Hexclave JWT Structure
Hexclave JWTs contain standardized headers and claims that power authentication throughout the platform.Header
alg: AlwaysES256kid: Identifies which public key from the JWKS should be used for verification
Standard Claims
iss(Issuer):https://api.hexclave.com/api/v1/projects/<project-id>for regular users, orhttps://api.hexclave.com/api/v1/projects-anonymous-users/<project-id>for anonymous sessionssub(Subject): The user ID this token representsaud(Audience): The intended recipient of the token —<project-id>for regular sessions,<project-id>:anonfor anonymous sessionsexp(Expiration): When the token expires (Unix timestamp)iat(Issued At): When the token was issued (Unix timestamp)
Hexclave Specific Claims
project_id: Your Hexclave project IDbranch_id: The project branch (currently alwaysmain)refresh_token_id: ID of the associated refresh tokenrole: Always set toauthenticatedfor valid usersname: The user’s display name (nullable)email: The user’s primary email address (nullable)email_verified: Whether the user’s email has been verifiedselected_team_id: The currently selected team ID (nullable)is_anonymous: Whether this is an anonymous user sessionis_restricted: Whether the user is restricted (e.g., unverified email, anonymous, or restricted by an administrator)restricted_reason: Why the user is restricted (nullable). Thetypefield isanonymous,email_not_verified, orrestricted_by_administrator
Example JWT Payload
Here’s what a typical Hexclave JWT payload looks like:issbecomeshttps://api.hexclave.com/api/v1/projects-anonymous-users/<project-id>audbecomes<project-id>:anonis_anonymousistrueis_restrictedistruerestricted_reasonis{ "type": "anonymous" }
issbecomeshttps://api.hexclave.com/api/v1/projects-restricted-users/<project-id>audbecomes<project-id>:restrictedis_restrictedistruerestricted_reasonis{ "type": "email_not_verified" }
issbecomeshttps://api.hexclave.com/api/v1/projects-restricted-users/<project-id>audbecomes<project-id>:restrictedis_restrictedistruerestricted_reasonis{ "type": "restricted_by_administrator" }
Working with JWTs
Client-Side Usage
Hexclave automatically handles JWT tokens for you. When you use hooks likeuseUser(), the JWT is automatically included in API requests:
Next.js:
Server-Side Usage
On the server side, you can access the JWT and its claims through the Hexclave API:Manual JWT Verification
If you need to manually verify a JWT (for example, in a different service), fetch the public keys from Hexclave’s JWKS endpoint. Keys are derived per audience so thekid in the JWT header always matches one of the published keys.
include_restricted=true:
Signing Keys
- Private keys are deterministically derived from your project ID, optional anonymous audience, and the
STACK_SERVER_SECRETenvironment variable. This means no key material is ever stored in the database. - The JWKS currently exposes both the latest key pair and a legacy compatibility key. Verification libraries automatically pick the correct key by matching the
kidprovided in the JWT header. - Tokens are always signed server-side; client SDKs never receive the private keys.
Security Considerations
Token Storage
- Never store JWTs in localStorage for sensitive applications
- Use secure, httpOnly cookies when possible
- Hexclave handles secure token storage automatically
Token Expiration
- JWTs have a limited lifetime (default is 10 minutes via
STACK_ACCESS_TOKEN_EXPIRATION_TIME) - Hexclave automatically refreshes tokens before they expire
- Always check the
expclaim when manually handling JWTs
Signature Verification
- Always verify JWT signatures using the public key
- Never trust the contents of a JWT without verification
- Hexclave SDKs handle verification automatically
Troubleshooting
Common Issues
- “JWT is expired”: The token has passed its expiration time. Hexclave will automatically refresh it.
- “Invalid signature”: The token was tampered with or signed with a different key.
- “Invalid audience”: The token was issued for a different project or environment.
Debugging JWTs
Use a JWT viewer such as jwt.io to inspect tokens and verify their contents. Pay special attention to:- Expiration times (
expclaim) - Audience (
audclaim) matching your project - Required claims are present
Best Practices
- Let Hexclave handle tokens: Use the provided SDKs instead of manual JWT handling
- Validate on the server: Always verify JWTs on your backend
- Check expiration: Ensure tokens haven’t expired before using them
- Use HTTPS: Always transmit JWTs over secure connections
- Monitor token usage: Log authentication events for security monitoring
Related Concepts
- API Keys - Alternative authentication method for server-to-server communication
- Setup - How to verify user sessions in your backend
- Permissions - Understanding user permissions (not included in JWTs)
- Teams - Understanding team context in JWTs