Skip to content

feat: SSO/OIDC provider integration (Sprint 20)#136

Merged
BadgerOps merged 18 commits intomasterfrom
feat/sso-oidc
Feb 19, 2026
Merged

feat: SSO/OIDC provider integration (Sprint 20)#136
BadgerOps merged 18 commits intomasterfrom
feat/sso-oidc

Conversation

@BadgerOps
Copy link
Owner

Summary

  • Generic OIDC provider integration using coreos/go-oidc/v3 + golang.org/x/oauth2 with Authorization Code Flow
  • JIT user provisioning from IdP claims with configurable group-to-role mapping
  • Silent session re-authentication via prompt=none hidden iframe for OIDC users
  • AES-256-GCM client secret encryption at rest
  • Local auth toggle — disable password login when OIDC is configured (break-glass admin preserved)
  • User active-status cache in DualAuthMiddleware (30s TTL via sync.Map)
  • Full admin CRUD API for OIDC providers with test connection endpoint
  • OIDC provider management UI in Config > Security settings (add/edit/delete providers, role mapping editor, test connection)
  • SSO login buttons on login page (one per enabled provider)

New API Endpoints

  • GET /api/v1/auth/oidc/providers — list enabled providers (public)
  • GET /api/v1/auth/oidc/login — initiate OIDC login flow
  • GET /api/v1/auth/oidc/callback — handle IdP callback with JIT provisioning
  • POST /api/v1/auth/oidc/refresh — silent re-auth redirect URL
  • GET/POST /api/v1/settings/oidc/providers — admin list/create
  • GET/PATCH/DELETE /api/v1/settings/oidc/providers/{id} — admin CRUD
  • POST /api/v1/settings/oidc/providers/{id}/test — test provider discovery

New Environment Variables

  • CLOUDPAM_OIDC_ENCRYPTION_KEY — 32-byte hex AES key (auto-generated if unset)
  • CLOUDPAM_OIDC_CALLBACK_URL — callback URL (default: http://localhost:8080/api/v1/auth/oidc/callback)

Test plan

  • All Go tests pass (go test ./... -count=1)
  • Zero lint issues (golangci-lint run ./...)
  • Default build succeeds (go build ./cmd/cloudpam)
  • SQLite build succeeds (go build -tags sqlite ./cmd/cloudpam)
  • TypeScript type check passes (npx tsc --noEmit)
  • Frontend production build succeeds (npm run build)
  • Manual test with Authentik or other OIDC IdP

Closes #130, closes #131

🤖 Generated with Claude Code

BadgerOps and others added 17 commits February 18, 2026 16:14
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…y impl

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements all 7 methods of the OIDCProviderStore interface for the
SQLite storage backend: CreateProvider, GetProvider, GetProviderByIssuer,
ListProviders, ListEnabledProviders, UpdateProvider, and DeleteProvider.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add claims.go with Claims struct and MapRole function for IdP group-to-role
mapping. Add provider.go wrapping coreos/go-oidc + oauth2 with NewProvider
(OIDC discovery), AuthCodeURL, and Exchange methods. Includes mock OIDC
server tests with RSA-signed JWTs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a 30-second TTL cache for user active-status lookups in the session
authentication path. Deactivated users are now blocked within 30 seconds
of deactivation without adding a DB query per request.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Check local_auth_enabled setting before accepting password login.
When disabled, returns 403 directing users to SSO.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add handleOIDCLogin (redirect to IdP), handleOIDCCallback (exchange code,
JIT user provisioning, session creation), handleOIDCRefresh (silent re-auth),
and handleListPublicProviders. Includes comprehensive test coverage.

Also adds GetByOIDCIdentity to UserStore interface with implementations
for memory, SQLite, and PostgreSQL stores.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add admin endpoints for managing OIDC provider configurations:
- GET/POST /api/v1/settings/oidc/providers (list, create)
- GET/PATCH/DELETE /api/v1/settings/oidc/providers/{id}
- POST /api/v1/settings/oidc/providers/{id}/test (discovery test)

Client secrets are encrypted at rest (AES-256-GCM) and masked in
API responses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add useOIDCProviders hook to fetch enabled OIDC providers.
Show "Sign in with {name}" buttons below the login form when
OIDC providers are configured. Uses direct server redirect
to the identity provider's authorization endpoint.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Initialize OIDCProviderStore, encryption key, and OIDCServer.
Register OIDC public routes and admin routes.
Add OIDC paths to CSRF exemption list.
Wire settingsStore into UserServer for local auth toggle.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace SSO/OIDC placeholder with full provider management:
- Provider list with add/edit/delete
- Provider config form (issuer, client ID/secret, scopes, roles)
- Test Connection button per provider
- Role mapping configuration
- Local auth toggle with confirmation
- Add local_auth_enabled to SecuritySettings type

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add useSessionRefresh hook that monitors session lifetime and
triggers prompt=none re-auth when session enters last 20% of
its lifetime. Update OIDC callback to detect iframe mode via
Sec-Fetch-Dest header and return postMessage instead of redirect.
Extend /auth/me response with auth_provider and session_expires_at.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…bles

- HTML-escape errParam in OIDC callback iframe response to prevent
  reflected XSS (CodeQL go/reflected-xss)
- URL-encode errParam in redirect to prevent parameter injection
- Add users, sessions, and settings table creation to PostgreSQL
  migration 0017, since these tables only existed in SQLite migrations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Owner Author

@BadgerOps BadgerOps left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@BadgerOps BadgerOps merged commit b3a5acb into master Feb 19, 2026
16 checks passed
@BadgerOps BadgerOps deleted the feat/sso-oidc branch February 19, 2026 01:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OIDC User Provisioning (JIT) SSO/OIDC Provider Integration

1 participant