Skip to content

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.signature

Header:

{
  "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
}
ClaimDescription
issIssuer — always https://auth.roled.id
subSubject — contains user ID (for user tokens) or client ID (for client tokens)
audAudience — the project ID this token belongs to
jtiJWT ID — unique identifier for this token
uidUser ID — present in user tokens
cidClient ID — always present, identifies which client issued the token
iatIssued At — Unix timestamp when the token was created
expExpiry — Unix timestamp when the token expires

User Tokens vs. Client Tokens

The uid claim distinguishes user tokens from client tokens:

User TokenClient Token
subUser IDClient ID
uidPresent (user’s ID)Not present
cidPresent (client used to authenticate)Present
audProject IDProject 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 (uid claim) or a client (cid claim).
  • The sub claim 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.