Authentication
Authentication in Strøm is optional. When no auth section is present in server-config.yaml, all API routes work without authentication. Adding the auth section enables JWT-based authentication.
Server configuration
Section titled “Server configuration”auth: jwt_secret: "your-jwt-secret" refresh_secret: "your-refresh-secret" base_url: "https://stroem.company.com" # Required for OIDC providers: internal: provider_type: internal # OIDC SSO provider: # google: # provider_type: oidc # display_name: "Google" # issuer_url: "https://accounts.google.com" # client_id: "your-client-id.apps.googleusercontent.com" # client_secret: "your-client-secret" initial_user: email: admin@stroem.local password: adminFields
Section titled “Fields”| Field | Required | Description |
|---|---|---|
jwt_secret | Yes | Secret for signing JWT access tokens (15-minute TTL) |
refresh_secret | Yes | Secret for refresh token operations (30-day TTL, rotation on use) |
base_url | OIDC only | Public URL of the server (for redirect URI construction) |
providers | Yes | Authentication providers map |
initial_user | No | Seeds an initial user on startup if one doesn’t already exist |
Internal authentication
Section titled “Internal authentication”The internal provider enables email/password login with argon2id password hashing.
providers: internal: provider_type: internalToken flow
Section titled “Token flow”- User logs in via
POST /api/auth/loginwith email and password - Server returns an access token (15-minute TTL) and refresh token (30-day TTL)
- Client includes the access token in
Authorization: Bearer <token>headers - When the access token expires, client uses
POST /api/auth/refreshwith the refresh token - Server returns a new access/refresh token pair (old refresh token is revoked)
OIDC SSO
Section titled “OIDC SSO”Strøm supports OIDC (OpenID Connect) for single sign-on via providers like Google, GitHub, Azure AD, and Okta.
providers: google: provider_type: oidc display_name: "Google" issuer_url: "https://accounts.google.com" client_id: "your-client-id.apps.googleusercontent.com" client_secret: "your-client-secret"- User clicks the SSO button in the UI
- Server redirects to the identity provider (Authorization Code + PKCE flow)
- User authenticates with the provider
- Provider redirects back to
/api/auth/oidc/{provider}/callback - Server validates the callback, provisions the user if needed, and issues internal JWT tokens
- User is redirected to the UI with tokens in the URL fragment
JIT user provisioning
Section titled “JIT user provisioning”When a user authenticates via OIDC for the first time:
- If an auth link for this provider + external ID exists → return that user
- If a user with the same email exists → create an auth link and return that user
- Otherwise → create a new user (no password) + auth link
API keys
Section titled “API keys”API keys provide long-lived tokens for programmatic and CI/CD access. They are tied to a user account and provide the same access as that user.
Creating API keys
Section titled “Creating API keys”Use the Settings page in the UI, or the API directly:
# Create a key (requires JWT auth)curl -X POST https://stroem.example.com/api/auth/api-keys \ -H "Authorization: Bearer <jwt-token>" \ -H "Content-Type: application/json" \ -d '{"name": "CI Pipeline", "expires_in_days": 90}'The response includes the raw key (shown only once):
{ "key": "strm_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4", "name": "CI Pipeline", "prefix": "strm_a1b", "expires_at": "2026-05-27T12:00:00Z"}Using API keys
Section titled “Using API keys”Use the key as a Bearer token in the Authorization header, exactly like a JWT:
curl https://stroem.example.com/api/jobs \ -H "Authorization: Bearer strm_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4"API keys work with the CLI too — set the token in the CLI config or pass it directly.
Key format
Section titled “Key format”Keys use the format strm_ followed by 32 random hex characters (37 characters total). The strm_ prefix lets the server distinguish API keys from JWT tokens. Only a SHA256 hash of the key is stored in the database.
Managing keys
Section titled “Managing keys”- List:
GET /api/auth/api-keys(returns prefix, name, dates — never the raw key) - Revoke:
DELETE /api/auth/api-keys/{prefix} - Keys can optionally have an expiration date
- The
last_used_attimestamp tracks when each key was last used
Web UI behavior
Section titled “Web UI behavior”The UI automatically detects whether authentication is enabled by calling GET /api/config. When auth is enabled, the login page is shown. When disabled, the UI proceeds directly to the dashboard.
Helm deployment
Section titled “Helm deployment”Use extraSecretEnv to inject secrets:
server: config: auth: jwt_secret: "placeholder" refresh_secret: "placeholder" initial_user: email: admin@example.com password: "placeholder" extraSecretEnv: STROEM__AUTH__JWT_SECRET: "real-jwt-secret" STROEM__AUTH__REFRESH_SECRET: "real-refresh-secret" STROEM__AUTH__INITIAL_USER__PASSWORD: "real-admin-password"Authorization (ACL)
Section titled “Authorization (ACL)”Once authentication is enabled, you can optionally configure access control lists to restrict which users can see and execute tasks. See Authorization for details on ACL rules, admin users, and group management.
See Auth API for the full endpoint reference.