Skip to content

Authentication

ValuePact uses JSON Web Tokens (JWT) for API authentication. Tokens are issued by Clerk and validated by the API gateway on every request.

Who this is for

Developer Admin Support

How authentication works

  1. User signs in via Clerk (email/password, SSO, or MFA).
  2. Clerk issues a short-lived JWT access token (default 1 hour) and a longer-lived refresh token.
  3. Your application includes the access token in the Authorization: Bearer <token> header.
  4. The API gateway validates the token signature, expiry, and tenant claims.
  5. The request proceeds only if all checks pass.

Token types

Type Lifetime Use
Access token 1 hour API requests
Refresh token 7 days Obtain a new access token
Session token Browser session Frontend session management

Obtaining a token

Browser applications

Use the Clerk SDK to handle sign-in and token retrieval:

import { useAuth } from '@clerk/clerk-react';

const { getToken } = useAuth();
const token = await getToken();

Backend services

Backend services use machine-to-machine authentication with service tokens:

POST /v1/auth/token
Content-Type: application/json

{
  "client_id": "your-client-id",
  "client_secret": "your-client-secret",
  "grant_type": "client_credentials"
}

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600
}

Using tokens in requests

Include the token in every API request:

GET /v1/initiatives
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
X-Tenant-ID: your-tenant-id

Tenant ID in header

The X-Tenant-ID header is required for multi-tenant API requests. The API validates that the authenticated user is a member of the specified tenant.

Token refresh

When an access token expires, use the refresh token to obtain a new one:

POST /v1/auth/refresh
Content-Type: application/json

{
  "refresh_token": "your-refresh-token"
}

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "refresh_token": "new-refresh-token",
  "expires_in": 3600
}

Automatic refresh

The Clerk JavaScript SDK handles token refresh automatically. For custom implementations, refresh the token when you receive a 401 response.

Token claims

A valid JWT contains these claims:

Claim Description
sub User ID
org_id Organization (tenant) ID
roles Array of role names
permissions Array of permission strings
iat Issued at timestamp
exp Expiration timestamp

Permissions

Permissions are granular capabilities assigned to roles:

Permission Description
initiatives:read View initiatives
initiatives:write Create and edit initiatives
initiatives:delete Delete initiatives
business_cases:read View business cases
business_cases:write Create and edit business cases
business_cases:approve Approve business cases
analytics:read View analytics and reports
admin:users Manage users
admin:roles Manage roles and permissions
admin:config Manage organization settings

See Administration → Permissions for the full permission matrix.

API keys (legacy)

API keys are deprecated in favor of JWT tokens. Existing API keys continue to work but new integrations should use JWT authentication.

GET /v1/initiatives
X-API-Key: vp_live_xxxxxxxxxxxxxxxx

SSO and SAML

For organizations using SSO:

  1. Configure SAML or OIDC in Administration → SSO.
  2. Users authenticate via your identity provider.
  3. Tokens are issued automatically after successful SSO authentication.

Multi-factor authentication

When MFA is enforced:

  1. User provides primary credentials.
  2. System prompts for MFA code (TOTP or SMS).
  3. After MFA verification, the token is issued.

See Administration → MFA for configuration.

Troubleshooting

Token rejected with 401

Cause: Token expired, malformed, or signature invalid. Resolution: Check token expiry. Refresh the token if expired. Verify the Authorization header format is exactly Bearer <token>.

Token valid but 403 returned

Cause: User lacks permission for the requested operation or tenant. Resolution: Verify the user's role includes the required permission. Confirm X-Tenant-ID matches an organization the user belongs to.

Refresh token rejected

Cause: Refresh token expired or was revoked. Resolution: Re-authenticate the user to obtain a new token pair. Check if the user's session was terminated by an admin.

CORS errors in browser

Cause: API requests from browser without proper CORS configuration. Resolution: Use the Clerk SDK which handles CORS automatically. For custom implementations, ensure your domain is allowlisted in the API gateway CORS policy.

Limits

Limit Token rate limit: 100 token requests per minute per IP.

Limit Maximum 5 concurrent sessions per user.