Tokens Explained
Optare uses three types of tokens. Understanding them is key to building secure applications.
Token Types at a Glance
| Token | Purpose | Lifetime | Stored Where |
|---|---|---|---|
| Access Token | Authorize API requests | 15 min - 1 hour | Memory (frontend) |
| ID Token | Identify the user | 1 hour | Memory (frontend) |
| Refresh Token | Get new access tokens | 7 - 30 days | Secure storage |
Access Token
The Access Token is your key to the API. Include it in every API request.
What's Inside
{
"sub": "user_abc123",
"aud": "https://api.myapp.com",
"iss": "https://id.optare.one",
"exp": 1703001600,
"scope": "read:data write:data",
"org_id": "org_xyz789"
}| Field | Meaning |
|---|---|
sub | User ID |
aud | Who the token is for (your API) |
iss | Who issued the token (Optare) |
exp | Expiration timestamp |
scope | What actions are allowed |
org_id | User's organization (B2B) |
How to Use It
// Include in API requests
fetch('/api/data', {
headers: {
'Authorization': `Bearer ${accessToken}`
}
});Important Rules
- ✅ Store in memory only (not localStorage)
- ✅ Short-lived (15 min - 1 hour)
- ❌ Never expose to other users
- ❌ Never log the full token
ID Token
The ID Token contains information about the authenticated user. Used for displaying user info in your UI.
What's Inside
{
"sub": "user_abc123",
"email": "john@acme.com",
"name": "John Doe",
"picture": "https://...",
"email_verified": true,
"org_id": "org_xyz789",
"org_name": "Acme Corp",
"role": "admin"
}How to Use It
// Get user info from ID token
const { user } = useOptare();
return (
<div>
<img src={user.picture} />
<p>Welcome, {user.name}!</p>
<p>Organization: {user.org_name}</p>
</div>
);Important Rules
- ✅ Use for UI display
- ✅ Contains user profile data
- ❌ Don't send to your API (use Access Token instead)
- ❌ Don't trust it for authorization on the server
Refresh Token
The Refresh Token is used to get new access tokens without re-authenticating.
The Refresh Flow
1. Access Token expires
↓
2. SDK automatically uses Refresh Token
↓
3. Optare issues new Access Token
↓
4. User continues without interruptionHow It Works
// The SDK handles this automatically
const client = new OptareClient({
// ...config
onTokenRefresh: (newToken) => {
// Optional: track when tokens refresh
console.log('Token refreshed');
}
});Important Rules
- ✅ Store securely (httpOnly cookie or secure storage)
- ✅ Long-lived (7-30 days)
- ✅ Can be revoked server-side
- ❌ Never expose to JavaScript if possible
- ❌ Never share between users
Token Lifecycle
User Login
↓
┌────────────────────────────────────────┐
│ Access Token (15 min) │
│ ID Token (1 hour) │
│ Refresh Token (30 days) │
└────────────────────────────────────────┘
↓
Access Token Expires
↓
Refresh Token → New Access Token
↓
... repeat until Refresh Token expires
↓
User must log in againSecurity Best Practices
Frontend (Browser)
| Token | Storage | Why |
|---|---|---|
| Access Token | Memory | Cleared on page close |
| ID Token | Memory | Cleared on page close |
| Refresh Token | httpOnly cookie | Not accessible to JS |
Backend (Server)
- Always validate Access Tokens on every request
- Check
expclaim to ensure token is not expired - Check
audclaim to ensure token is for your API - Check
issclaim to ensure token is from Optare
import * as jose from 'jose';
const { payload } = await jose.jwtVerify(token, JWKS, {
issuer: 'https://id.optare.one',
audience: 'https://api.myapp.com',
});Next Steps
- Identity Fundamentals - OAuth and OIDC basics
- Node.js Quickstart - Validate tokens in your API
- Security Best Practices - Production security checklist