Skip to content

Authentication (User Login)

This document covers how users authenticate to the Jarvis UI — browser login, session management, roles, and provider setup.

For how Jarvis authenticates against a protected Alertmanager (service-to-service), see authentication-alertmanager.md.


Jarvis supports three authentication modes, controlled by the JARVIS_AUTH_PROVIDER environment variable.

ModeDescription
noneNo login required. All write actions are publicly accessible. Default.
internalLocal user accounts with bcrypt passwords. A first-run wizard creates the admin account.
oidcDelegate login to an external OIDC provider (Keycloak, Authentik, Dex, etc.).

Quick Start

No authentication (default)

env
JARVIS_AUTH_PROVIDER=none

Anyone who can reach Jarvis can read alerts and perform write actions (claims, comments, silences). Suitable for private networks with no external access.

On first load, Jarvis shows a one-time notice explaining that authentication is not configured:

No-auth notice

Internal accounts

env
JARVIS_AUTH_PROVIDER=internal
JARVIS_SECRET_KEY=<min 32 random bytes>

On first access, Jarvis redirects to /setup where you create the initial admin account. Additional users are managed under Administration in the user menu.

Generate a secret key:

bash
openssl rand -hex 32

OIDC (Keycloak, Authentik, etc.)

env
JARVIS_AUTH_PROVIDER=oidc
JARVIS_SECRET_KEY=<min 32 random bytes>
JARVIS_AUTH_OIDC_ISSUER=https://keycloak.example.com/realms/myrealm
JARVIS_AUTH_OIDC_CLIENT_ID=jarvis
JARVIS_AUTH_OIDC_CLIENT_SECRET=<client-secret>
JARVIS_AUTH_OIDC_REDIRECT_URL=https://jarvis.example.com/auth/oidc/callback
JARVIS_AUTH_OIDC_SCOPES=openid,profile,email

Protection Level (JARVIS_AUTH_MODE)

When JARVIS_AUTH_PROVIDER is internal or oidc, JARVIS_AUTH_MODE determines how strictly unauthenticated access is blocked.

ValueBehaviour
write_protect(default) Unauthenticated users can view alerts and silences read-only. Write operations — creating/deleting comments, claims, and silences — require a valid session. A Login button appears in the header.
full_protectAll API routes and the UI require authentication. Unauthenticated users are shown a full-screen login page and cannot access any alert data until they sign in.

JARVIS_AUTH_MODE is ignored (forced to none) when JARVIS_AUTH_PROVIDER=none.

Choosing a mode:

  • Use write_protect for internal teams where read access to alerts is acceptable without login (e.g. NOC screens, ops dashboards).
  • Use full_protect for public-facing deployments or any environment where alert data must not be visible to unauthenticated users.

Environment Variables

The full reference (defaults, which are required per provider, descriptions) is in Configuration → User authentication. JARVIS_OIDC_GROUPS_CLAIM / JARVIS_OIDC_ADMIN_VALUE are explained further under Role Mapping below.


Internal Provider — First-Run Wizard

When JARVIS_AUTH_PROVIDER=internal and no admin account exists in the database, Jarvis redirects every request to /setup.

  1. Open Jarvis in the browser — you land on the setup page automatically.
  2. Enter a username and password (min 12 characters).
  3. Submit — the admin account is created and you are redirected to the main view.

The setup endpoint is disabled once at least one user exists in the database.

First-run setup page

After setup, users log in via the login modal (triggered by the Login button in the header):

Login modal — internal

Logging in never costs you your place

Whenever something needs a session, the login modal opens on top of the page you are on and the interrupted action carries on once you are logged in — nothing navigates, nothing is reset. This holds for every write (silences, claims, comments, templates, expiring silences):

  • Not logged in yet: buttons stay usable. In the silence form, Preview works without a session; the login is asked at Create, on top of the finished form, and the silence is created straight after.
  • Session expired while you worked: if the session token ran out unnoticed, the first write that comes back 401 opens the modal (titled Session expired) and is replayed automatically after you log in.
  • full_protect: a session that expires while the app is open keeps the page mounted and shows a modal you cannot dismiss; the full-page login screen only appears when you were never logged in.

A modal you dismiss simply drops the pending action.

Administration

Admins manage users under Administration in the user menu (API: /api/v1/admin/users):

  • Create new users (role: user or admin)
  • Reset passwords
  • Delete users

The panel is only accessible to users with the admin role. Open it from the user menu in the header (top right corner).

User menu

Admin panel — User Management


OIDC Provider

Jarvis uses the Authorization Code Flow with PKCE. No client-side secrets are exposed to the browser.

The login modal shows a single Login with SSO button:

Login modal — OIDC

From the modal the SSO login runs in a popup window, so the page underneath — a half-filled silence form, an open alert — stays exactly as it is; as soon as the login succeeds the popup is closed for you and the interrupted action completes. If the browser blocks the popup, Jarvis falls back to a full-page redirect that brings you back to the page you left (/auth/oidc/start?return_to=<in-app path>; only same-origin in-app paths are honoured, anything else lands on /). The full-page login screen (full_protect) uses the same return_to, so a deep link with filters survives the round trip.

Flow

OIDC login flow

OIDC login flow

(source: docs/diagrams/oidc-login-flow.mmd, re-render via make diagrams)

Keycloak Setup

  1. Create a new client in your realm with:
    • Client ID: jarvis
    • Client authentication: on (confidential client)
    • Valid redirect URIs: https://jarvis.example.com/auth/oidc/callback
  2. Copy the client secret from the Credentials tab.
  3. Set JARVIS_AUTH_OIDC_ISSUER=https://keycloak.example.com/realms/<realm>.

Authentik Setup

  1. Create an OAuth2/OpenID Provider with:
    • Authorization flow: default (implicit or explicit)
    • Redirect URIs: https://jarvis.example.com/auth/oidc/callback
  2. Create an Application linked to that provider.
  3. Set JARVIS_AUTH_OIDC_ISSUER=https://authentik.example.com/application/o/<slug>/.

Role Mapping

OIDC users get the user role by default. There are two ways to grant admin rights.

From a token claim. Set both variables and Jarvis reads the role straight from the ID token on every login:

env
JARVIS_OIDC_GROUPS_CLAIM=groups
JARVIS_OIDC_ADMIN_VALUE=jarvis-admins

The claim may be a single string or a list — Keycloak's groups and Cognito's cognito:groups both work. A user whose claim contains the configured group becomes admin, everyone else stays user. Because this is evaluated at each login, revoking the group in the identity provider takes effect the next time the user signs in.

Seeing your groups. With JARVIS_OIDC_GROUPS_CLAIM set, the Account panel (your name in the user menu) lists your name, role and the groups the identity provider reported, plus when that was. Jarvis stores the groups at each login, so a change in the identity provider shows up only after you sign in again — the sessions below last 24 hours. If someone reports a missing alert, ask them for this list.

Upgrading from 1.x: JARVIS_OIDC_ADMIN_CLAIM was renamed to JARVIS_OIDC_GROUPS_CLAIM, with no alias. The old variable is ignored, so rename it before upgrading or every SSO user becomes a plain user at the next login.

Not by hand. An SSO user's role is set from the token at every login, so a promotion made in the admin panel lasts only until that user signs in again. Without a claim mapping every SSO user is a plain user.


Sessions

Sessions are stored as signed JWT cookies:

PropertyValue
Cookie namejarvis_session
TTL24 hours
HttpOnlyyes (not accessible via JavaScript)
SameSiteLax
Secureyes when served over HTTPS (detected via X-Forwarded-Proto)

User Settings Storage

With an auth provider active, a signed-in user's Settings (theme, default view, saved filters, etc. — see Features → User Settings) are stored server-side against the account and follow them across devices. Without an auth provider (JARVIS_AUTH_PROVIDER unset) — or while signed out in write_protect mode — settings stay in that browser's localStorage only. Signing in for the first time on a device copies any local settings to the account once; after that the account always wins. Signing out falls back to the browser's own settings without touching the account's.


Roles

RoleCapabilities
userRead alerts, create/delete own claims and comments, create silences
adminAll user capabilities + manage users under Administration

Kubernetes / Helm

yaml
auth:
  provider: internal    # none | internal | oidc
  mode: ""              # write_protect (default) | full_protect — ignored when provider=none
  secretKey: ""         # use existingSecret in production
  existingSecret: ""    # K8s Secret containing secret-key (and oidc-client-secret)
  existingSecretKeys:
    secretKey: secret-key
    oidcClientSecret: oidc-client-secret
  oidc:
    issuer: ""
    clientId: ""
    clientSecret: ""    # stored in the auth Secret
    redirectUrl: ""
    scopes: "openid,profile,email"

Internal auth with chart-managed secret

yaml
auth:
  provider: internal
  secretKey: "$(openssl rand -hex 32)"

Internal auth with external secret

bash
kubectl create secret generic jarvis-auth \
  --from-literal=secret-key=$(openssl rand -hex 32)
yaml
auth:
  provider: internal
  existingSecret: jarvis-auth

OIDC with external secret

bash
kubectl create secret generic jarvis-auth \
  --from-literal=secret-key=$(openssl rand -hex 32) \
  --from-literal=oidc-client-secret=<your-client-secret>
yaml
auth:
  provider: oidc
  existingSecret: jarvis-auth
  oidc:
    issuer: https://keycloak.example.com/realms/myrealm
    clientId: jarvis
    redirectUrl: https://jarvis.example.com/auth/oidc/callback

For a full values reference see charts/jarvis/README.md.


Security Notes

  • JARVIS_SECRET_KEY is never written to logs. Use at least 32 random bytes.
  • OIDC client secret is stored in a Kubernetes Secret, not in the ConfigMap.
  • The /setup endpoint is automatically disabled once any user account exists.
  • All cookies are HttpOnly — the session token is not readable by JavaScript.
  • SameSite=Lax prevents CSRF on cross-site form submissions.
  • The Administration panel and its API (/api/v1/admin/*) require the admin role and are protected by RequireAdmin middleware.

For vulnerability reporting and supported versions, see the Security Policy.

Released under the Apache 2.0 License. Jarvis is not affiliated with Prometheus or Alertmanager.