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.
Enable authentication
Section titled “Enable authentication”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.
How sign-in works
Section titled “How sign-in works”- A user opens S3 Lens and hits a protected page
- The browser is redirected to
GET /api/auth/login - S3 Lens starts an Authorization Code flow with PKCE against your OIDC provider
- After the user signs in, the provider redirects to
GET /api/auth/callback - S3 Lens validates the ID token and sets an HttpOnly
s3lens_sessioncookie - Subsequent API requests include the cookie automatically
Sign out via GET /api/auth/logout.
Public endpoints
Section titled “Public endpoints”These routes work without a session:
GET /api/healthGET /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.
Identity provider setup
Section titled “Identity provider setup”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 membershipMapping users to roles
Section titled “Mapping users to roles”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 |
Group bindings
Section titled “Group bindings”Map IdP groups to app roles:
auth: bindings: - groups: ["s3lens-viewers"] role: viewer - groups: ["s3lens-editors"] role: editorDirect policy assignment
Section titled “Direct policy assignment”Assign policies to specific users by subject (JWT sub claim):
auth: bindings: - subjects: ["contractor-42"] policies: [custom-readonly]Local users (development)
Section titled “Local users (development)”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.
Built-in roles and test setup
Section titled “Built-in roles and test setup”s3lens.yaml.example includes a full auth setup for local testing with Docker Compose and Keycloak:
just compose-updocker compose logs keycloak-bootstrap # wait for "Done."cp s3lens.yaml.example s3lens.yamls3lens --config s3lens.yaml --host 127.0.0.1 --port 8080Keycloak 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).
UI permissions
Section titled “UI permissions”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.
Reverse-proxy authentication
Section titled “Reverse-proxy authentication”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.
Next steps
Section titled “Next steps”Define what each role can do: Access policies