Tokens
A token is a signed proof of identity that Roled issues after a successful authentication. Roled uses the JWT (JSON Web Token) standard for all access tokens.
What Is a Token?
After a user or client successfully authenticates, Roled issues a JWT access token.
This token proves who the caller is (user or client), is cryptographically signed (cannot be tampered with), and has an expiry time.
It is used in every subsequent API request as a Bearer token.
sequenceDiagram
autonumber
participant C as User or Client
participant R as Roled
C->>R: Authenticate (Authorization Code or Client Credentials)
R->>R: Validate credentials
R->>R: Create access token record
R->>R: Sign JWT with secret key
R-->>C: JWT access token
C->>R: API Request with Bearer JWT
R->>R: Validate JWT + resolve permissions
R-->>C: Response
JWT Structure
A Roled JWT is a standard JWT with custom claims. It has three parts separated by dots:
header.payload.signatureHeader:
{
"alg": "HS256",
"typ": "JWT"
}Payload (Claims):
{
"iss": "https://auth.roled.id",
"sub": "<user_id>",
"aud": "<project_id>",
"jti": "<token_id>",
"uid": "<user_id>",
"cid": "<client_id>",
"iat": 1753780300,
"exp": 1753866700
}| Claim | Description |
|---|---|
iss | Issuer — always https://auth.roled.id |
sub | Subject — contains user ID (for user tokens) or client ID (for client tokens) |
aud | Audience — the project ID this token belongs to |
jti | JWT ID — unique identifier for this token |
uid | User ID — present in user tokens |
cid | Client ID — always present, identifies which client issued the token |
iat | Issued At — Unix timestamp when the token was created |
exp | Expiry — Unix timestamp when the token expires |
User Tokens vs. Client Tokens
The uid claim distinguishes user tokens from client tokens:
| User Token | Client Token | |
|---|---|---|
sub | User ID | Client ID |
uid | Present (user’s ID) | Not present |
cid | Present (client used to authenticate) | Present |
aud | Project ID | Project ID |
Access Token Details Endpoint
After obtaining a token, you can call the /tokens/current endpoint to get detailed information about the authenticated identity, including their role and permissions:
curl --request GET \
--url https://auth.roled.id/api/v1/tokens/current \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJo...'Response:
{
"success": true,
"data": {
"id": "2JTsCIYytiCinRkhtWVN2q",
"issued_at": "2026-07-29T10:00:00Z",
"expires_at": "2026-07-29T11:00:00Z",
"project": {
"id": "2JUSLUee46xG6iEwG8JwPc",
"name": "Business App",
"description": "App for managing business operations",
"logo_url": "https://example.com/logo.png"
},
"client": {
"id": "2JRYkzSeBV89itqcU9mraF",
"name": "Main Client"
},
"user": {
"id": "2JRtk7i2aEFKpsKTNx6YWR",
"display_name": "Alice Smith",
"email": "alice.smith@example.com",
"external_user_id": "921f28239dcd",
"avatar_url": "https://example.com/profiles/alice-smith.jpg"
},
"role": {
"id": "2JRtjyxfZudzaJkFczgoUY",
"code": "store-manager",
"name": "Store Manager",
"description": "Manages store operations including products, orders, and staff"
},
"permissions": [
"products:create",
"products:read",
"products:update",
"products:delete",
"orders:read",
"orders:update",
"users:read"
]
}
}This endpoint is useful for your application to check the current user’s identity, role, and permissions in a single call.
Permissions Are Not in the JWT
Roled intentionally keeps JWTs small and lightweight. Permissions are not embedded in the token payload. Instead, they are resolved server-side on every request.
This approach allows for several benefits:
- Permission changes take effect immediately, no waiting for tokens to expire.
- JWTs stay small, resulting in faster transmission and parsing.
- The authorization model is centrally managed.
Refresh Tokens
User tokens (from the Authorization Code Flow) also include a refresh token. Refresh tokens allow your application to obtain a new access token without requiring the user to log in again.
Exchange response with refresh token:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJo...",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "d2h5LWRvLXlvdS1yZWFkLXRoaXM...",
"refresh_token_expires_in": 604800
}Client tokens (from Client Credentials Flow) do not have refresh tokens. The client simply re-authenticates when its token expires.
Revoking Tokens
You can revoke a token at any time:
curl --request POST \
--url https://auth.roled.id/api/v1/tokens/current/revoke \
--header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJo...' \
--header 'Content-Type: application/json' \
--data '{
"client_id": "2JRYkzSeBV89itqcU9mraF",
"refresh_token": "d2h5LWRvLXlvdS1yZWFkLXRoaXM..."
}'Once revoked, the token is immediately invalidated. This is possible because Roled validates every JWT against its database record on each request.
Key Points
- Roled issues JWT access tokens after authentication.
- Tokens identify either a user (
uidclaim) or a client (cidclaim). - The
subclaim contains the user or client ID based on the identity authenticated. - Permissions are not in the JWT, they are resolved server-side on every request.
- Applications can use the Access Token Details endpoint to get the current user’s or client’s permissions.
- User tokens include a refresh token for seamless session renewal.