JWT Tokens
JWT (JSON Web Tokens) provide time-bound authentication for browser-based applications and server-to-server communication. Tokens are obtained via the login endpoint and refreshed as needed.
Obtaining a Token
Via Email/Password Login
POST to /api/v1/auth/login with email and password:
curl -X POST https://api.truthvouch.com/api/v1/auth/login \ -H "Content-Type: application/json" \ -d '{ "grantType": "password", "email": "user@company.com", "password": "SecurePassword123!" }'Response:
{ "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refreshToken": "rt_1234567890abcdef", "expiresIn": 3600, "tokenType": "Bearer"}Token Structure
Each JWT contains the following claims:
{ "sub": "user-uuid", "email": "user@company.com", "client_id": "org-uuid", "role": "admin", "subscription_tier": "professional", "iat": 1678886400, "exp": 1678890000}Claims:
sub— Unique user ID (use for audit trails)email— User email addressclient_id— Organization / account ID (all API requests filtered by this)role— User role:admin,developer,viewersubscription_tier— Plan level:sandbox,professional,enterpriseiat— Issued at (Unix timestamp)exp— Expires at (Unix timestamp)
Using JWT Tokens
Setting Authorization Header
Include the access token in the Authorization header:
curl -X GET https://api.truthvouch.com/api/v1/governance/alerts \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."In Python SDK
from truthvouch import TruthVouchClient
client = TruthVouchClient( gateway_url="https://gateway.truthvouch.com", jwt_token="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...")In TypeScript SDK
import TruthVouch from '@truthvouch/sdk';
const tv = new TruthVouch({ jwtToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'});In Browser (JavaScript)
const response = await fetch('https://api.truthvouch.com/api/v1/governance/alerts', { method: 'GET', headers: { 'Authorization': 'Bearer ' + accessToken }});const data = await response.json();Token Lifetime
- Access Token: 1 hour (3600 seconds)
- Refresh Token: 30 days (2,592,000 seconds)
After an access token expires, use the refresh token to obtain a new one without re-authenticating.
Refreshing Tokens
When your access token is about to expire (check the exp claim), refresh it using the refresh token:
curl -X POST https://api.truthvouch.com/api/v1/auth/refresh \ -H "Content-Type: application/json" \ -d '{ "grantType": "refresh_token", "refreshToken": "rt_1234567890abcdef" }'Response:
{ "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refreshToken": "rt_9876543210fedcba", "expiresIn": 3600, "tokenType": "Bearer"}Refresh Token Rotation
For security, the refresh token is rotated on each refresh. Always use the new refresh token from the response.
Handling Token Expiration
Check Before Expiry
Decode the JWT to check the exp claim (Unix timestamp):
import jsonimport base64from datetime import datetime
def is_token_expired(token): parts = token.split('.') payload = json.loads(base64.urlsafe_b64decode(parts[1] + '==')) expires_at = payload['exp'] return datetime.utcnow().timestamp() > expires_at
# Refresh if less than 5 minutes remainingtoken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."if is_token_expired(token): # Call refresh endpointHandle 401 Responses
If a request returns 401 Unauthorized:
- The token has expired or been revoked
- Use the refresh token to obtain a new access token
- Retry the original request
- If refresh also fails, re-authenticate (ask user to login)
Security Best Practices
1. Store Tokens Securely
In Browser:
- Use
httpOnlycookies (server sets via Set-Cookie header) - Never store in localStorage (vulnerable to XSS)
In Server/App:
- Store in memory or secure session storage
- Never log tokens
- Never commit tokens to source control
2. Use HTTPS Only
Always communicate over HTTPS to prevent token interception.
3. Never Share Tokens
- Tokens are user-specific
- Do not embed tokens in URLs
- Do not share via email or chat
4. Rotate Refresh Tokens
Always use the new refresh token from the response. Old refresh tokens should be discarded.
5. Handle Expiration Gracefully
Refresh tokens before they expire to avoid interrupting user workflows.
6. Validate Token Claims
When receiving a token from a client, verify:
- Signature is valid (use your public key)
expclaim is in the futureclient_idmatches your expected organization ID
Common Errors
”Invalid credentials”
Email or password is incorrect.
Fix: Verify credentials and try again.
”401 Unauthorized”
Access token is missing, invalid, or expired.
Fix:
- Check that the token is in the
Authorization: Bearerheader - Check the token hasn’t expired (decode and check
expclaim) - If expired, refresh using the refresh token
- If refresh fails, re-authenticate
”403 Forbidden”
Token is valid but the user doesn’t have permission for this operation.
Fix: Check the user’s role and subscription tier in the token claims.
”Refresh token expired”
Refresh tokens are only valid for 30 days.
Fix: Re-authenticate by calling /api/v1/auth/login again.