Authentication
Toggly supports multiple authentication methods for accessing the API, including OAuth 2.0, and JWT Bearer tokens.
Authentication Methods
OAuth 2.0 Client Credentials (Recommended for API Integration)
For machine-to-machine (M2M) API access, Toggly uses OAuth 2.0 Client Credentials flow. This is ideal for server-side applications, scripts, or automated processes.
Configuration
- Token Endpoint:
https://auth.toggly.io/connect/token - Grant Type:
client_credentials - Token Type: JWT Bearer
- Required Scopes:
openid,toggly
Obtaining Client Credentials
- Log in to your Toggly account at https://app.toggly.io
- Navigate to Team Settings → API Keys
- Click Create API Key
- Copy your Client ID and Client Secret (store securely - the secret is only shown once)
Getting an Access Token
Send a POST request to the token endpoint:
curl -X POST https://auth.toggly.io/connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "scope=openid toggly"
Response:
{
"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjE...",
"expires_in": 3600,
"token_type": "Bearer",
"scope": "openid toggly"
}
Using the Access Token
Include the access token in the Authorization header for all API requests:
curl -X GET https://app.toggly.io/api/v2/applications \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjE..."
Token Expiration
- Access tokens are valid for 1 hour (3600 seconds)
- When a token expires, request a new one using the same client credentials
- No refresh token is issued for client credentials flow
Best Practices
- Secure Storage: Never commit client secrets to source control. Use environment variables or secret management systems.
- Token Caching: Cache access tokens and reuse them until they expire to minimize token requests.
- Error Handling: Implement automatic token refresh when receiving
401 Unauthorizedresponses. - Scope Restrictions: Only request the scopes your application needs.
Example: Token Refresh Logic
let cachedToken = null;
let tokenExpiry = null;
async function getAccessToken() {
// Return cached token if still valid
if (cachedToken && tokenExpiry && Date.now() < tokenExpiry) {
return cachedToken;
}
// Request new token
const response = await fetch('https://auth.toggly.io/connect/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: process.env.TOGGLY_CLIENT_ID,
client_secret: process.env.TOGGLY_CLIENT_SECRET,
scope: 'openid toggly'
})
});
const data = await response.json();
cachedToken = data.access_token;
tokenExpiry = Date.now() + (data.expires_in * 1000) - 60000; // Refresh 1 min early
return cachedToken;
}
OAuth 2.0 / JWT Bearer (Interactive Login)
The Toggly web application and Chrome Extension use OAuth 2.0 with JWT Bearer tokens for interactive user authentication:
- Authorization Endpoint:
https://auth.toggly.io/connect/authorize - Token Endpoint:
https://auth.toggly.io/connect/token - Token Type: JWT Bearer
- Scopes:
openid,email,toggly
Token Lifecycle
Token Issuance
When you sign in to Toggly:
- You authenticate via OAuth 2.0 (with PKCE for the Chrome Extension)
- An access token and refresh token are issued
- The access token is valid for a limited time (typically 1 hour)
- The refresh token can be used to obtain new access tokens
Token Refresh
Before an access token expires:
- The client sends the refresh token to the token endpoint
- A new access token is issued
- The new token replaces the old one
- The old token is no longer valid
Token Invalidation
When you sign out, tokens are immediately invalidated server-side to prevent unauthorized access.
Token Invalidation API
Endpoint
POST /api/account/invalidate-token
Description
Invalidates the current JWT access token by adding it to a server-side blacklist. This ensures the token cannot be used after logout, even if it hasn't expired yet.
Authentication
Requires a valid JWT Bearer token in the Authorization header.
Request
curl -X POST https://app.toggly.io/api/account/invalidate-token \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Response
Success (200 OK):
{
"message": "Token invalidated successfully"
}
Unauthorized (401):
{
"error": "invalid_token",
"error_description": "No bearer token provided"
}
Bad Request (400):
{
"error": "invalid_token",
"error_description": "Invalid JWT token format"
}
How It Works
- Client Calls Endpoint: When signing out, the client sends a POST request with the access token
- Token Hashing: The server computes a SHA256 hash of the token (for security)
- Blacklist Storage: The token hash is stored in Redis with a TTL matching the token's expiration
- Validation Check: All subsequent API requests check if the token is blacklisted
- Automatic Cleanup: Blacklisted tokens are automatically removed when they expire
Security Features
- Immediate Revocation: Tokens are invalidated instantly, not after expiration
- Hash Storage: Only a hash of the token is stored, never the full token
- Automatic Expiry: Blacklist entries are automatically cleaned up
- High Performance: Redis-based blacklist provides sub-millisecond lookup times
- Privacy Preserving: No sensitive token data is persisted
Token Validation
When you make an API request with a JWT Bearer token:
- Signature Verification: The token signature is verified using the public key
- Expiration Check: The token expiration time is checked
- Blacklist Check: The token is checked against the invalidation blacklist
- Claims Extraction: User claims (sub, role, teams) are extracted from the token
If any check fails, the request is rejected with 401 Unauthorized.
Best Practices
1. Always Sign Out
When you're done working, always sign out properly. This ensures your tokens are invalidated server-side:
// Chrome Extension automatically calls the invalidation endpoint
await authService.signOut();
2. Handle 401 Responses
If you receive a 401 Unauthorized response, your token may have been invalidated or expired:
// Automatically refresh token or redirect to login
if (response.status === 401) {
await refreshToken();
// or
redirectToLogin();
}
3. Secure Token Storage
Store tokens securely:
- Browser: Use secure, HttpOnly cookies or browser storage APIs
- Chrome Extension: Use
chrome.storage.local(neverlocalStorage) - Mobile Apps: Use secure storage (Keychain, Keystore)
- Never: Store tokens in code, logs, or version control
4. Token Rotation
For long-running applications, implement automatic token refresh:
// Refresh tokens before they expire
setInterval(async () => {
if (tokenExpiresInLessThan(5, 'minutes')) {
await refreshToken();
}
}, 5 * 60 * 1000); // Check every 5 minutes
5. Use HTTPS Only
Always use HTTPS when sending tokens:
- Never send tokens over HTTP
- Verify SSL certificates
- Use certificate pinning for mobile apps (optional)
Error Codes
| Code | Description | Action |
|---|---|---|
401 | Unauthorized - invalid or expired token | Refresh token or re-authenticate |
403 | Forbidden - insufficient permissions | Check user permissions |
429 | Too many requests - rate limit exceeded | Implement exponential backoff |
Token Claims
JWT tokens issued by Toggly include these claims:
- sub: User ID (e.g.,
ApplicationUsers/1-A) - email: User email address
- name: User full name
- role: User role (e.g.,
User,Admin) - team: Team IDs the user belongs to
- primaryTeam: User's primary team ID
- iat: Issued at timestamp
- exp: Expiration timestamp
- aud: Audience (optional)
- iss: Issuer (
https://auth.toggly.io)
Support
For authentication issues:
- Check the Troubleshooting guide
- Review Security & Compliance documentation
- Contact support at [email protected]