Skip to content

feat: replace custom session auth with FerrisKey OIDC (Auth.js v5)#11

Open
asmuelle wants to merge 1 commit into
mainfrom
feat/ferriskey-auth
Open

feat: replace custom session auth with FerrisKey OIDC (Auth.js v5)#11
asmuelle wants to merge 1 commit into
mainfrom
feat/ferriskey-auth

Conversation

@asmuelle

Copy link
Copy Markdown
Owner

Identity is now owned by FerrisKey (Keycloak-alternative IAM) over OIDC via Auth.js v5. Scope is authentication only: workspace tenancy + owner/member role stay in the local memberships table, re-derived per request (Invariant 8).

  • core/db: add app_user.external_subject + linkOrCreateUserBySubject (memory + Drizzle), migration 0006. Match by IdP sub, else verified-email backfill, else JIT-create. Unverified-email collision is rejected (IdentityConflictError) to prevent account takeover.
  • web: apps/web/auth.ts custom OIDC provider (PKCE, jwt/session callbacks pin the local user id) + [...nextauth] route. resolveWorkspace keyed by {userId}; resolveActiveWorkspace rides on auth(). Remove hand-rolled session-crypto/secret.
  • ui: "Continue with FerrisKey" sign-in; Auth.js sign-out + hint-cookie clear; switchWorkspace fails closed before writing the hint.
  • infra: FerrisKey API/console/Postgres in docker-compose (profile auth, pg 5434); just ferriskey-up/down/bootstrap; scripts/ferriskey-bootstrap.ts.
  • hardening: baseline security headers, Auth.js error->sign-in routing.
  • env/docs: AUTH_SECRET + FERRISKEY_* ; TOOLS.md, DESIGN.md, ROADMAP updated.

Identity is now owned by FerrisKey (Keycloak-alternative IAM) over OIDC via
Auth.js v5. Scope is authentication only: workspace tenancy + owner/member role
stay in the local memberships table, re-derived per request (Invariant 8).

- core/db: add app_user.external_subject + linkOrCreateUserBySubject (memory +
  Drizzle), migration 0006. Match by IdP sub, else verified-email backfill, else
  JIT-create. Unverified-email collision is rejected (IdentityConflictError) to
  prevent account takeover.
- web: apps/web/auth.ts custom OIDC provider (PKCE, jwt/session callbacks pin the
  local user id) + [...nextauth] route. resolveWorkspace keyed by {userId};
  resolveActiveWorkspace rides on auth(). Remove hand-rolled session-crypto/secret.
- ui: "Continue with FerrisKey" sign-in; Auth.js sign-out + hint-cookie clear;
  switchWorkspace fails closed before writing the hint.
- infra: FerrisKey API/console/Postgres in docker-compose (profile auth, pg 5434);
  just ferriskey-up/down/bootstrap; scripts/ferriskey-bootstrap.ts.
- hardening: baseline security headers, Auth.js error->sign-in routing.
- env/docs: AUTH_SECRET + FERRISKEY_* ; TOOLS.md, DESIGN.md, ROADMAP updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
token,
json: { temporary: false, credential_type: 'password', value: DEMO_PASSWORD },
});
console.log(`✓ demo user ${DEMO_EMAIL} ready (password: ${DEMO_PASSWORD})`);
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.

2 participants