OIDC: library route (go-oidc + x/oauth2) — decision resolved #7

Merged
Cordy merged 22 commits from oidc-lib into main 2026-07-20 17:26:24 +00:00
Owner

Merges the winning OIDC variant per external expert review (see OIDC-COMPARISON.md, now carrying the decision record).

What lands (from oidc-common + oidc-lib):

  • internal/auth: memory session store + cookies, /auth/login|callback|logout endpoints, challenge semantics (browser → IdP redirect; WebDAV/API → Basic 401), Flow interface, Multi provider chain, shared verifyLimiter (issue-#5 OOM protection refactored for reuse)
  • App passwords: atomic-JSON store, Basic-auth provider (prefix-gated, bounded argon2, fingerprint cache), REST endpoints POST/GET/DELETE /api/v1/app-passwords
  • internal/auth/oidclib: OIDC flow via go-oidc/v3 + x/oauth2 — discovery, Code+PKCE, single-use expiring state, nonce binding, library-verified ID tokens (RS256/ES256 allow-list), claims mapping
  • Config: oidcRedirectUrl/oidcScopes/oidcUsernameClaim/oidcGroupsClaim/appPasswordsPath + CAIRN_OIDC_CLIENT_SECRET env
  • cmd/cairnd: auth.mode: "oidc" fully wired
  • Full test suites: sessions/app-passwords/OIDC provider + fake-IdP attack suite (alg=none, HS256 confusion, tampered sig, wrong iss/aud/nonce, expiry, state replay, PKCE)
  • go.mod: +go-oidc/v3, +x/oauth2, +go-jose/v4 (indirect); Go floor moves to 1.25 (go-oidc requirement)

Not in scope / follow-ups: real-IdP e2e (deploy Keycloak/Authentik on k3s), LDAP provider, UI for app-password management. oidc-stdlib and oidc-common branches are deleted after this merge; the hand-rolled verifier remains in git history.

Merges the winning OIDC variant per external expert review (see `OIDC-COMPARISON.md`, now carrying the decision record). **What lands (from oidc-common + oidc-lib):** - `internal/auth`: memory session store + cookies, `/auth/login|callback|logout` endpoints, challenge semantics (browser → IdP redirect; WebDAV/API → Basic 401), `Flow` interface, `Multi` provider chain, shared `verifyLimiter` (issue-#5 OOM protection refactored for reuse) - **App passwords**: atomic-JSON store, Basic-auth provider (prefix-gated, bounded argon2, fingerprint cache), REST endpoints `POST/GET/DELETE /api/v1/app-passwords` - `internal/auth/oidclib`: OIDC flow via `go-oidc/v3` + `x/oauth2` — discovery, Code+PKCE, single-use expiring state, nonce binding, library-verified ID tokens (RS256/ES256 allow-list), claims mapping - Config: `oidcRedirectUrl/oidcScopes/oidcUsernameClaim/oidcGroupsClaim/appPasswordsPath` + `CAIRN_OIDC_CLIENT_SECRET` env - `cmd/cairnd`: `auth.mode: "oidc"` fully wired - Full test suites: sessions/app-passwords/OIDC provider + fake-IdP attack suite (alg=none, HS256 confusion, tampered sig, wrong iss/aud/nonce, expiry, state replay, PKCE) - go.mod: +`go-oidc/v3`, +`x/oauth2`, +`go-jose/v4` (indirect); Go floor moves to 1.25 (go-oidc requirement) **Not in scope / follow-ups:** real-IdP e2e (deploy Keycloak/Authentik on k3s), LDAP provider, UI for app-password management. `oidc-stdlib` and `oidc-common` branches are deleted after this merge; the hand-rolled verifier remains in git history.
ci: run on oidc-* branch pushes (parallel OIDC prototyping)
All checks were successful
ci / test-and-build (push) Successful in 7s
2009b0b3a1
auth: extract bounded/deduped verification into verifyLimiter
Some checks failed
ci / test-and-build (push) Failing after 1s
7f3736dd3b
Shared by the local provider and the upcoming app-password provider so
both get the issue-#5 OOM protection from one implementation.
auth: Local uses the shared verifyLimiter (no behavior change)
All checks were successful
ci / test-and-build (push) Successful in 7s
05f9070170
auth: memory-only session store for OIDC browser sessions
All checks were successful
ci / test-and-build (push) Successful in 7s
b1d83e13dd
auth: app passwords — per-device secrets bridging WebDAV into OIDC mode
All checks were successful
ci / test-and-build (push) Successful in 8s
59b9fca0c5
Atomic-JSON file store (same pattern as internal/share.FileStore) plus a
Basic-auth Provider that recognizes the cairn- secret prefix, verifies
argon2id-hashed secrets through the shared verifyLimiter, and caches
accepted fingerprints like the local provider.
auth: Flow interface — the seam between the two OIDC prototype variants
All checks were successful
ci / test-and-build (push) Successful in 8s
bcf8c1617f
auth: OIDC session provider + auth endpoints + Multi chain
All checks were successful
ci / test-and-build (push) Successful in 8s
034bc9c4b5
Session-cookie Provider for auth.mode "oidc"; the browser flow itself is
delegated to a Flow implementation (variant branches). Challenge sends
HTML clients into the login flow and Basic clients a WWW-Authenticate
(app passwords answer those). Multi tries providers in order.
auth: tests for sessions, app passwords, OIDC provider, Multi chain
All checks were successful
ci / test-and-build (push) Successful in 9s
b6e526adbf
api: app-password management endpoints (OIDC mode)
Some checks failed
ci / test-and-build (push) Failing after 2s
8015fdad7f
api: register app-password endpoints when enabled
All checks were successful
ci / test-and-build (push) Successful in 8s
41c8e49436
config: OIDC redirect/scopes/claim names + app-passwords path
All checks were successful
ci / test-and-build (push) Successful in 9s
13120b820d
cairnd: variant seam — oidc-common ships no flow implementation
All checks were successful
ci / test-and-build (push) Successful in 9s
dc04d42b48
cairnd: wire auth.mode oidc — sessions + app passwords + flow seam
All checks were successful
ci / test-and-build (push) Successful in 9s
b19b2172e8
oidclib: OIDC flow via coreos/go-oidc + x/oauth2
Some checks failed
ci / test-and-build (push) Failing after 1s
563fc981e0
The library half of the OIDC build decision. Token verification is
delegated to go-oidc; this file owns state/nonce lifecycle and claims
mapping. go.mod/go.sum are regenerated by the go-tidy workflow.
oidclib: fake-IdP test suite — same attack cases as oidcstd
Some checks failed
ci / test-and-build (push) Failing after 2s
2a8bbb602c
cairnd: variant seam → go-oidc library flow (oidclib)
Some checks failed
ci / test-and-build (push) Failing after 2s
ec27931738
docs: OIDC variant comparison for expert review
Some checks failed
ci / test-and-build (push) Failing after 45s
aea99203a0
oidclib: fake IdP must declare application/json on /token
All checks were successful
ci / test-and-build (push) Successful in 31s
c2dad9ee3b
x/oauth2 parses non-JSON content types as form data and reported
"server response missing access_token". oidcstd's hand-rolled client
JSON-decodes regardless — an incidental robustness difference worth
noting in the comparison.
docs: record the OIDC build decision — library route chosen
Some checks failed
ci / test-and-build (pull_request) Failing after 16s
5e52c4ca49
Merge branch 'main' into oidc-lib
All checks were successful
ci / test-and-build (pull_request) Successful in 15s
f10269b352
Cordy merged commit 0a64bbbb21 into main 2026-07-20 17:26:24 +00:00
Cordy deleted branch oidc-lib 2026-07-20 17:26:27 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#7
No description provided.