Skip to content

Authentication and Security

Will Luck edited this page Apr 13, 2026 · 5 revisions

Authentication and Security

Login


First-Run Setup

On first start with no existing users, Sentinel displays a setup wizard at /setup. The wizard creates the initial admin account and marks setup as complete. Once complete, the /setup endpoint is permanently disabled.

If the container is started with SENTINEL_AUTH_ENABLED=false, all requests are treated as an authenticated admin with full permissions. This is intended for local/development use only.


Password Authentication

Property Detail
Hashing bcrypt (cost 12)
Minimum length 8 characters
Maximum length 72 bytes (bcrypt limit, enforced explicitly)
Complexity At least one letter and one digit
Username Case-sensitive
Rate limit 5 failed attempts per IP in a 5-minute window
Account lockout 10 consecutive failures locks the account for 30 minutes

Passwords are stored as bcrypt hashes. The 72-byte limit is enforced before hashing to prevent bcrypt's silent truncation.

Login routes:

Method Path Purpose
GET /login Render login page
POST /login Submit credentials
POST /api/auth/logout End session

Two-Factor Authentication (TOTP)

Time-based one-time passwords using the standard TOTP algorithm (RFC 6238). Compatible with any TOTP app (Google Authenticator, Authy, 1Password, etc.).

Setup Flow

  1. Navigate to Settings > Security and click Enable 2FA.
  2. Sentinel generates a secret and displays a QR code.
  3. Scan the QR code with your authenticator app.
  4. Enter a valid 6-digit code to confirm. 2FA is not active until this step completes.
  5. Save the 8 recovery codes shown. Each code is single-use. Recovery codes are stored as SHA-256 hashes.

Login with 2FA

When TOTP is enabled, the login flow becomes two-step:

  1. Submit username and password. On success, the server returns a pending TOTP token (valid for 5 minutes).
  2. Submit the 6-digit TOTP code (or a recovery code) with the pending token. On success, a session is created.

Recovery codes are consumed on use. If all recovery codes are exhausted, an admin can disable 2FA on the account.

Disabling 2FA

Requires the account password for confirmation. Clears the TOTP secret and all recovery codes.

Setting Value
Issuer Docker-Sentinel
Algorithm SHA-1 (standard TOTP)
Digits 6
Period 30 seconds
Recovery codes 8, single-use, SHA-256 hashed

WebAuthn / Passkeys

FIDO2 passwordless authentication via hardware keys, biometrics, or platform authenticators. Opt-in, requires environment variables before use.

Variable Purpose Example
SENTINEL_WEBAUTHN_RPID Relying Party ID, must match the host serving the UI sentinel.example.com
SENTINEL_WEBAUTHN_ORIGINS Comma-separated allowed origins https://sentinel.example.com
SENTINEL_WEBAUTHN_DISPLAY_NAME Human-readable site name shown in authenticator prompts Docker Sentinel

When at least one passkey is registered, a Use passkey option appears on the login page. Multiple passkeys can be registered per account. Manage them under Settings > Security.

WebAuthn ceremonies (registration and assertion) have a 60-second TTL. If the user does not complete the ceremony within that window, it expires and must be restarted.

The availability endpoint (GET /api/auth/passkeys/available) is public and returns {"available": true} when passkeys are configured server-side.

Auth Settings


OIDC / SSO

OpenID Connect integration for single sign-on with external identity providers (Keycloak, Authentik, Authelia, Google, etc.).

OIDC is configured from the web UI at Settings > Security > OIDC, or via the API.

Setting Description
Issuer URL OIDC discovery endpoint (e.g. https://auth.example.com/realms/main)
Client ID OAuth2 client identifier
Client Secret OAuth2 client secret
Redirect URL Callback URL, typically https://sentinel.example.com/api/auth/oidc/callback
Auto-create users Create local accounts from OIDC claims on first login
Default role Role assigned to auto-created users (admin, operator, or viewer)

Login Flow

  1. User clicks Sign in with SSO on the login page.
  2. Sentinel generates a CSRF state token, an OIDC nonce, and a PKCE code verifier (S256). All three are stored in HttpOnly cookies (oidc_state, oidc_nonce, oidc_pkce).
  3. Browser redirects to the identity provider's authorization endpoint with the state, nonce, and PKCE code challenge.
  4. After authentication, the provider redirects back with an authorization code.
  5. Sentinel exchanges the code for an ID token using the PKCE verifier, then validates the nonce claim with constant-time comparison.
  6. Claims are extracted (preferred_username, email, name). If the username matches an existing local account, a session is created.
  7. If no match exists and auto-create is enabled, a new user is created with the configured default role.

OIDC users are assigned a random password (they authenticate via the identity provider, not via the Sentinel login form).

The nonce and PKCE protections are automatic - no additional configuration is required. They guard against replay attacks and authorization code interception respectively.

Requested Scopes

openid, profile, email

API Endpoints

Method Path Purpose
GET /api/auth/oidc/available Check if OIDC is configured (public)
GET /api/auth/oidc/login Initiate OIDC flow (redirects to IdP)
GET /api/auth/oidc/callback Handle IdP redirect
GET /api/settings/oidc Read OIDC settings (admin)
POST /api/settings/oidc Save OIDC settings (admin)

RBAC

Three built-in roles with ten granular permissions. Roles are assigned per user at creation or via Settings > Users.

Roles

Role Description
Admin Full access to all features including user management and settings
Operator Container operations (view, update, approve, rollback, manage) and read-only settings
Viewer Read-only access to containers, settings, logs, and history

Permission Matrix

Permission Admin Operator Viewer Description
containers.view Yes Yes Yes Read container list, detail, queue, stats, SSE stream
containers.update Yes Yes Trigger scans, pull updates, switch registry source
containers.approve Yes Yes Approve, reject, or ignore pending updates
containers.rollback Yes Yes Roll back containers or services
containers.manage Yes Yes Start, stop, restart, set per-container policy
settings.view Yes Yes Yes Read all settings, hooks, dependencies, cluster info
settings.modify Yes Write settings, manage notifications/registries/cluster
users.manage Yes Create, delete, and configure user accounts
logs.view Yes Yes Yes Read activity logs
history.view Yes Yes Yes Read update history

Sessions

Property Detail
Token format 64-character lowercase hex (32 random bytes)
Generation crypto/rand
Storage BoltDB
Default expiry 720 hours (30 days)
Expiry override SENTINEL_SESSION_EXPIRY (e.g. 168h)
Cookie name sentinel_session
Cookie flags HttpOnly, SameSite=Lax
Secure flag Set when SENTINEL_COOKIE_SECURE=true

Sessions are listed and individually revocable from the Account page or via the API. Expired sessions are cleaned up periodically.

Session rotation: each successful login creates a new session token. Old sessions are not reused.

Logout

Logout is available only via POST /logout. The GET /logout route is intentionally not registered - logout must be a CSRF-protected state-changing request. The CSRF double-submit check applies, so the X-CSRF-Token header (or csrf_token form field) is required.


API Tokens

Long-lived bearer tokens for automation and scripting.

Property Detail
Format stk_ prefix + base64url-encoded 32 random bytes
Storage SHA-256 hash only; plaintext shown once at creation
Transport Authorization: Bearer stk_... header
CSRF Exempt (not cookie-based)
Scope Supports optional expiry and permission scoping
Last used Tracked automatically on each request

Permission Scoping

API tokens can be restricted to a subset of the creating user's permissions. The effective permissions are the intersection of the user's role permissions and the token's declared scope. Tokens with no explicit scope inherit all permissions from the user's role.

Example

# List containers using an API token
curl -H "Authorization: Bearer stk_abc123..." \
  https://sentinel.example.com/api/containers

Tokens with no expiry remain valid until deleted. Manage tokens from Settings > Security or via the API.


Webhook Authentication

The webhook endpoint (POST /api/webhook) uses its own secret-based authentication, separate from session or token auth.

The secret must be passed via the X-Webhook-Secret header. Query-string authentication (?secret=...) is not supported - proxies and access logs record URLs verbatim, which would leak the secret into log aggregators and browser history.

curl -X POST http://your-server:8080/api/webhook \
  -H "X-Webhook-Secret: your_secret" \
  -H "Content-Type: application/json" \
  -d '{"push_data":{"tag":"latest"},"repository":{"repo_name":"myuser/myapp"}}'

The secret is compared using constant-time comparison to prevent timing attacks. Generate or rotate the secret from Settings > Webhooks in the UI, or via POST /api/settings/webhook-secret.


CSRF Protection

Sentinel uses the double-submit cookie pattern for cross-site request forgery protection.

Component Detail
Cookie name sentinel_csrf
Cookie flags Not HttpOnly (JavaScript must read it), SameSite=Lax
Header X-CSRF-Token
Form field csrf_token (fallback for HTML form submissions)
Applies to POST, PUT, DELETE, PATCH requests with session cookies
Exempt Bearer token requests, requests when auth is disabled
Comparison Constant-time (crypto/subtle)

On each mutating request, the server compares the sentinel_csrf cookie value against the X-CSRF-Token header (or csrf_token form field) using constant-time comparison. A mismatch returns HTTP 403.


Rate Limiting

Login attempts are rate-limited per IP address.

Parameter Value
Window 5 minutes
Max attempts per window 5
Account lockout threshold 10 consecutive failures
Account lockout duration 30 minutes
Cleanup interval 1 hour

After 5 failed attempts from an IP within a 5-minute window, further attempts are rejected. After 10 consecutive failures on a specific account, that account is locked for 30 minutes regardless of IP.

Successful login resets both the IP rate limit counter and the account failure counter.


TLS

Mode Configuration
Reverse proxy (recommended) Run Sentinel on HTTP behind a proxy; no extra config needed
Bring your own certificate SENTINEL_TLS_CERT=/path/cert.pem and SENTINEL_TLS_KEY=/path/key.pem
Auto self-signed SENTINEL_TLS_AUTO=true, generates and stores a cert on first start

When using built-in TLS, also set SENTINEL_COOKIE_SECURE=true.

Reverse Proxy Examples

nginx with WebSocket and SSE support:

location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_buffering off;           # required for SSE
    proxy_cache off;
    proxy_read_timeout 86400s;     # keep SSE connection open
}

Caddy:

sentinel.example.com {
    reverse_proxy localhost:8080
}

Caddy handles TLS automatically via Let's Encrypt. No additional Sentinel config is required.


Cookie Reference

Cookie HttpOnly SameSite Secure Purpose
sentinel_session Yes Lax Configurable (SENTINEL_COOKIE_SECURE) Session authentication
sentinel_csrf No Lax Configurable CSRF double-submit value
oidc_state Yes Lax Configurable OIDC CSRF state (temporary, cleared after callback)
oidc_nonce Yes Lax Configurable OIDC nonce for replay protection (temporary, cleared after callback)
oidc_pkce Yes Lax Configurable PKCE code verifier for code interception protection (temporary, cleared after callback)

Dependency Security Notes

Recent dependency bumps addressing known vulnerabilities:

  • grpc v1.79.3 - fixes connection handling edge cases in the gRPC transport layer used by cluster communication.
  • go-jose v4.1.4 - fixes JWT parsing issues in the JOSE library used by the OIDC provider.

Keep Sentinel updated to the latest release to receive these and future security patches.


Environment Variable Reference

Variable Default Description
SENTINEL_AUTH_ENABLED true (DB default) Override auth on/off; false grants full admin to all requests
SENTINEL_SESSION_EXPIRY 720h Session lifetime
SENTINEL_COOKIE_SECURE true Set Secure flag on cookies
SENTINEL_TLS_CERT Path to TLS certificate PEM
SENTINEL_TLS_KEY Path to TLS private key PEM
SENTINEL_TLS_AUTO false Auto-generate self-signed certificate
SENTINEL_WEBAUTHN_RPID WebAuthn Relying Party ID
SENTINEL_WEBAUTHN_ORIGINS Comma-separated WebAuthn origins
SENTINEL_WEBAUTHN_DISPLAY_NAME Docker-Sentinel WebAuthn display name

Clone this wiki locally