This page covers how end users authenticate to psLens, what access controls exist (and which deliberately don’t), and how to front psLens with your existing identity provider today.

For SSO, see SSO Today.


1. How Users Log In Today

psLens ships with optional email magic-link authentication. It is off by default in the shipped config.yaml and must be turned on for production deployments.

When auth.enabled: true:

  1. User visits any psLens URL → redirected to /login.
  2. User enters their email address.
  3. psLens emails a one-time verification code to that address (only if the address is on the configured AuthorizedUsers allowlist).
  4. User enters the code at /verify-code.
  5. Session created in NATS KV, identified by an HTTP-only psLens_auth cookie.
PropertyValue
MechanismEmail one-time code (no passwords)
Session storageNATS KV bucket auth-sessions
Session TTL1 year (configurable)
CookiepsLens_auth, HTTP-only
User allowlistAuthorizedUsers in config.yaml, case-insensitive
Public endpoints (no auth required)/healthz, /static/*, the auth flow itself

There are no end-user passwords for psLens to store, leak, hash, or rotate.

Disabling auth entirely is supported only for sandbox or trusted-network deployments. The shipped config defaults to disabled so a first-time installer can get to a working UI quickly. Flip it on before exposing the instance.


2. The Deliberate Scope Decision: No In-App RBAC

psLens has no role-based access control inside the application. Every authenticated user sees the same set of metadata, can run the same reports, and can browse the same PS objects.

This is intentional, not an oversight:

For most customers, the population of people who need psLens (PS developers, sec admins, sys admins, business analysts doing audit work) is small and homogeneous. Adding in-app roles would create configuration overhead without changing the actual blast radius.

If your security policy requires per-user authorization decisions at the application layer, raise it on the demo call. The reverse-proxy patterns below can enforce this without requiring psLens itself to grow an RBAC model.


3. SSO Today: Reverse Proxy

The recommended pattern for any production deployment is to front psLens with a reverse proxy that handles SSO, and turn off the built-in magic-link layer. This delegates authentication to the IdP you already trust.

Common setups:

Reverse proxyIdentity providersNotes
Cloudflare AccessOkta, Azure AD, Google Workspace, OIDC, SAMLNo infrastructure for you to run; works with the fly.io-managed deployment
oauth2-proxyGoogle, GitHub, Azure AD, Keycloak, generic OIDCSelf-hosted; sidecar to psLens
PomeriumAny OIDC, SAMLSelf-hosted; richer policy engine
Tailscale with serveAny SSO that fronts TailscaleNetwork-layer; locks psLens to your tailnet
Nginx / Traefik / Caddy with forward_authAnything that speaks OIDCMost flexible; you own the wiring

The pattern is the same in every case:

  1. The reverse proxy terminates TLS, authenticates the user against your IdP, and only forwards authenticated requests to psLens.
  2. psLens trusts the proxy (binds to a private network or listens on 127.0.0.1).
  3. auth.enabled: false in psLens config. The proxy is the identity boundary.

Cross-link: the TLS termination patterns in Deployment Options cover the same reverse proxies and explain how to wire them up; this page is the identity-layer companion.

What the proxy can do that psLens RBAC could not: enforce group membership (“only the psoft-admins group in Okta”), require MFA, enforce conditional access policies (managed device, geo, time-of-day), and write to your existing IdP audit log.


4. Native SSO on the Roadmap

Native OIDC support inside psLens is planned. No committed date. This will let customers who don’t want a reverse-proxy hop configure their IdP directly in config.yaml.

We are deliberately not promising native SAML. The reverse-proxy patterns above already cover SAML; native OIDC closes the more common gap.

Until native SSO ships, reverse-proxy SSO is production-ready. It is the recommended deployment pattern for every customer with an enterprise IdP.


5. Session Management

ConcernBehavior
Where sessions liveNATS KV, bucket auth-sessions, scoped to this psLens instance
Cookie scopeHTTP-only, marked Secure when served over HTTPS
Idle timeoutNone today. Sessions live until the TTL expires.
Absolute TTL1 year (configurable per deployment)
Logout/logout clears the session entry from NATS KV
Mass invalidationRestart the container, or clear the auth-sessions bucket via nats kv. Useful after a credential incident.

A built-in admin-facing “kill all sessions” UI is on the roadmap. Today the NATS CLI path above is the supported route.


6. What Reviewers Usually Ask

“Can we require MFA?” Yes, by fronting with a reverse proxy that enforces MFA at the IdP layer (any of the proxies above). Magic-link auth on its own is single-factor (control of the email inbox).

“Where does the user email come from on the SWS side?” psLens authenticates its own users via magic-link or reverse-proxy SSO. Those are the people using the psLens UI. psLens authenticates to PeopleSoft via the SWS service account (basic auth, see Code & Supply Chain). The two identity domains are independent. Your psLens users do not need PS accounts.

“Can we revoke a user instantly?” Yes. Remove them from AuthorizedUsers and restart; their next request fails. With reverse-proxy SSO, revoke them at the IdP and they lose access on the next request, no restart needed.

“Does psLens store passwords?” No end-user passwords. The only password-shaped secret psLens holds is the SWS service-account password used to call PeopleSoft, encrypted at rest with AES-256-GCM. See Data Handling & Logging.