Authentication
Pennant uses JWT (HS256) tokens for the management API and SDK keys for the SDK endpoints.
Login
Exchange credentials for an access token and a refresh token.
Rate limit: 5 requests per minute per IP address.
Request:
curl -X POST http://localhost:8080/auth/login \
-H 'Content-Type: application/json' \
-d '{
"email": "admin@pennant.local",
"password": "admin"
}'
Response 200 OK:
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "7f3b2a1c9e4d5f6a8b2c3d4e5f6a7b8c..."
}
accessToken— JWT, valid for 1 hour. Include in subsequent API requests asAuthorization: Bearer <token>.refreshToken— opaque token, valid for 7 days. Single-use; rotate it before it expires.
Response 401 Unauthorized:
Refresh tokens
Exchange a refresh token for a new access/refresh token pair. Refresh tokens are single-use — the old token is invalidated when a new one is issued.
curl -X POST http://localhost:8080/auth/refresh \
-H 'Content-Type: application/json' \
-d '{
"refreshToken": "7f3b2a1c9e4d5f6a8b2c3d4e5f6a7b8c..."
}'
Response 200 OK:
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d..."
}
Get current user
Returns the authenticated user's profile and role.
Response 200 OK:
RBAC roles
| Role | Can do |
|---|---|
owner |
Everything, including deleting projects and managing users |
admin |
Create/edit/delete flags, segments, experiments, environments |
editor |
Create/edit flags and segments; cannot delete or manage environments |
viewer |
Read-only access to all resources |
All management API endpoints (/api/v1/...) require a valid JWT. The required role is checked per endpoint.
SDK key authentication
SDK endpoints (/sdk/v1/...) use SDK keys instead of JWTs. Pass the SDK key as a Bearer token:
SDK keys are scoped to a project + environment pair and do not grant access to the management API.
Token storage
- Store access tokens in memory (not in
localStorageor cookies, unless you implement CSRF protection). - Refresh tokens should be stored in an
HttpOnlycookie or a secure persistent store. - Never log or expose tokens in URLs, query parameters, or error messages.
Legacy token auth
If PENNANT_ADMIN_TOKEN is set (not recommended for new deployments), any request with Authorization: Bearer <token> matching that value receives owner access without JWT validation. This is provided for backward compatibility and automated scripts that predate the JWT implementation. Prefer creating a service account with a long-lived SDK key or a dedicated API user instead.