Skip to content

Authentication

S3 Lens supports OpenID Connect (OIDC) sign-in with server-side session cookies and policy-based authorization. When auth.enabled is false (the default), all API routes are open — suitable for local development only.

Do not expose S3 Lens to untrusted networks without authentication enabled.

Turn on auth and connect your identity provider:

policy:
enabled: true
use_defaults: true
roles:
viewer:
policies: [default-viewer]
editor:
policies: [default-viewer, default-write]
auth:
enabled: true
oidc:
issuer: "https://idp.example/realms/s3lens"
client_id: "s3lens"
client_secret: "${OIDC_CLIENT_SECRET}"
redirect_uri: "https://s3lens.example.com/api/auth/callback"
identity:
subject_claim: "sub"
groups_claim: "groups"
bindings:
- role: viewer
groups: ["s3lens-viewers"]
- role: editor
groups: ["s3lens-editors"]

Set S3LENS_SESSION_SECRET (32+ bytes) for production session signing.

  1. A user opens S3 Lens and hits a protected page
  2. The browser is redirected to GET /api/auth/login
  3. S3 Lens starts an Authorization Code flow with PKCE against your OIDC provider
  4. After the user signs in, the provider redirects to GET /api/auth/callback
  5. S3 Lens validates the ID token and sets an HttpOnly s3lens_session cookie
  6. Subsequent API requests include the cookie automatically

Sign out via GET /api/auth/logout.

These routes work without a session:

  • GET /api/health
  • GET /api/auth/login, /api/auth/callback, /api/auth/logout, /api/auth/me

When auth is enabled, the UI, OpenAPI docs (/api/openapi.json, /api/scalar), and status endpoints also require a valid session.

Register an OIDC client with your provider (Keycloak, Auth0, Okta, Azure AD, etc.) using:

Setting Value
Client type Confidential (requires client secret)
Redirect URI Your S3 Lens callback URL, e.g. https://s3lens.example.com/api/auth/callback
Grant type Authorization Code
Scopes At minimum openid; include profile and a groups claim if you use group bindings

Configure the matching values under auth.oidc in s3lens.yaml:

auth:
oidc:
issuer: "https://idp.example/realms/s3lens"
client_id: "s3lens"
client_secret: "${OIDC_CLIENT_SECRET}"
redirect_uri: "https://s3lens.example.com/api/auth/callback"
identity:
subject_claim: "sub" # JWT claim for user ID
groups_claim: "groups" # JWT claim for group membership

S3 Lens separates three concepts:

Concept Example Where it lives
Role editor, viewer Top-level roles: — bundles of policies you define
IdP group s3lens-editors Your identity provider — referenced in auth.bindings
Policy default-write Top-level policy.policies: — allow/deny rules

Map IdP groups to app roles:

auth:
bindings:
- groups: ["s3lens-viewers"]
role: viewer
- groups: ["s3lens-editors"]
role: editor

Assign policies to specific users by subject (JWT sub claim):

auth:
bindings:
- subjects: ["contractor-42"]
policies: [custom-readonly]

For testing without an IdP, assign roles directly:

auth:
local_users:
- subject: "local-editor"
roles: [editor]

Local users skip IdP group lookup. Remove local_users in production.

s3lens.yaml.example includes a full auth setup for local testing with Docker Compose and Keycloak:

Terminal window
just compose-up
docker compose logs keycloak-bootstrap # wait for "Done."
cp s3lens.yaml.example s3lens.yaml
s3lens --config s3lens.yaml --host 127.0.0.1 --port 8080

Keycloak test users (password = username):

User Role Access
viewer viewer Read-only, all providers
editor editor Read, write, and delete everywhere
garage garage-reader Read-only on Garage only
seaweed seaweed-editor Write/delete on SeaweedFS only
uploader uploader uploads/ prefix only
admin admin Full admin
nopresign viewer-no-presign Read-only, presign denied

Keycloak admin console: http://127.0.0.1:8081/admin (admin / admin).

GET /api/auth/me returns the signed-in user’s subject, groups, and allowed actions. The web UI uses this to show or hide upload, delete, and presign controls based on what the user is permitted to do.

Tools like oauth2-proxy can protect the network perimeter, but they cannot express S3 Lens action rules (per-bucket write, presign deny, provider-scoped access, and so on). Use OIDC plus access policies for application-level control. A reverse proxy can still add TLS termination or an extra authentication layer in front of S3 Lens.

Define what each role can do: Access policies