Commits
Add docker/setup-qemu-action before buildx to enable cross-platform
emulation for arm64 builds on GitHub Actions runners.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GitHub Actions QEMU emulation fails on arm64 builds. K8s deployment
is amd64-only anyway.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gateway: 2.2.0 → 2.4.0
Rust lib: 1.3.0 → 1.4.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevent accidental commit of security audit documents containing
environment-specific details.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes 5 HIGH, 16 MEDIUM, 14 LOW, 8 INFO findings across 7 phases:
- Token revocation blacklist via jti claims in SQLite (H-2)
- Session endpoint auth hardening with gateway token validation (H-1)
- Refresh token scope validation per RFC 6749 Section 6 (M-9)
- Removed plain PKCE from OIDC discovery, S256-only (H-3)
- Passkey challenges moved from in-memory to SQLite (M-4)
- TOTP replay protection via absolute period tracking (M-5)
- Email verification lockout after 5 failed attempts (M-8)
- OAuth PDS sessions moved from in-memory to SQLite (L-1)
- AES-256-GCM IV migration (16->12 bytes) with HKDF key derivation (L-3/L-4)
- JWT kid fallback hardened - reject when kid present but not found (L-2)
- WebAuthn requireUserVerification enforced (M-2)
- Webhook HTML escaping for XSS prevention (M-7)
- CSP form-action directive added (M-6)
- Recovery scope restricted to openid/profile/email (L-7)
- Cache-Control: no-store on token info endpoint (M-1)
- Docker image SHA pinning, compose security hardening (D-2/D-3)
- CI kubeconfig cleanup with mktemp+trap (D-1)
- Rust lib: zeroize secrets on drop, RwLock poison recovery,
removed unused postgres deps, pinned chrono, upgraded rusqlite
- OIDC presets: pkce_note documentation for disabled PKCE clients
423 tests passing, 0 npm vulnerabilities.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds /api/pds/write endpoint that proxies authenticated xRPC calls
to users' PDS via their stored OAuth sessions. Whitelists only
createRecord and putRecord for atchess.game and atchess.profile
collections. Validates Bearer token and enforces repo matches DID.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sends fire-and-forget login notifications to a Matrix room when users
authenticate to configured OIDC clients. Uses the Matrix Client-Server
API via an atauth-bot account. Configurable per-client via env vars.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add user-level access gating to OIDC clients and Legacy HMAC apps,
matching the existing forward-auth proxy access control pattern.
- New `client_access_rules` table for per-client allow/deny rules
- New `require_access_check` flag on apps table (default: off)
- Enforcement in OIDC authorize callback + passkey flow
- Enforcement in Legacy HMAC auth callback
- Admin API: CRUD endpoints + dry-run access check
- Generic `checkAccess()` now works with both proxy and client rules
- 19 new tests (423 total, all passing)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
github.repository_owner preserves case but Docker tags must be
lowercase. Use tr to normalize the image name.
github.repository_owner preserves case but Docker tags must be
lowercase. Use tr to normalize the image name.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Builds multi-arch Docker image (amd64 + arm64) and pushes to
ghcr.io/cache8063/atauth-gateway on version tag push.
Builds multi-arch Docker image (amd64 + arm64) and pushes to
ghcr.io/cache8063/atauth-gateway on version tag push.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove DO-HANDOFF.md (deployment-specific ops document)
- Update HOMELAB.md clone URL to GitHub
- Update CHANGELOG.md comparison links to GitHub
- Add v2.3.0 changelog entry
- Add GitHub Actions CI workflow (test on push/PR)
- Remove DO-HANDOFF.md (deployment-specific ops document)
- Update HOMELAB.md clone URL to GitHub
- Update CHANGELOG.md comparison links to GitHub
- Add v2.3.0 changelog entry
- Add GitHub Actions CI workflow (test on push/PR)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add passkey/WebAuthn support to the forward-auth proxy login flow,
previously only available in the OIDC authorize flow:
- New POST /auth/proxy/passkey endpoint
- Passkey button + WebAuthn JS on proxy login page
- 9 new tests for proxy passkey flow
Security fixes from audit:
- MFA verify endpoints require authentication (prevent unauthenticated brute-force)
- Session expiry enforced in database query
- OIDC logout redirect uses origin comparison (prevent open redirect)
- PKCE plain method rejected, S256 uses constant-time comparison
- Empty DID guard in token endpoint
- Handle format validation in OIDC authorize
- trust proxy configured for correct client IP
- user_id NaN validation
- Removed uuid package (use crypto.randomUUID())
Add passkey/WebAuthn support to the forward-auth proxy login flow,
previously only available in the OIDC authorize flow:
- New POST /auth/proxy/passkey endpoint
- Passkey button + WebAuthn JS on proxy login page
- 9 new tests for proxy passkey flow
Security fixes from audit:
- MFA verify endpoints require authentication (prevent unauthenticated brute-force)
- Session expiry enforced in database query
- OIDC logout redirect uses origin comparison (prevent open redirect)
- PKCE plain method rejected, S256 uses constant-time comparison
- Empty DID guard in token endpoint
- Handle format validation in OIDC authorize
- trust proxy configured for correct client IP
- user_id NaN validation
- Removed uuid package (use crypto.randomUUID())
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add GET /version returning service name, package version, and build
commit SHA. Pass BUILD_COMMIT as Docker build arg through CI pipeline.
Include deployment inventory and RCA docs from infrastructure
consolidation (single K8s atauth instance).
Add GET /version returning service name, package version, and build
commit SHA. Pass BUILD_COMMIT as Docker build arg through CI pipeline.
Include deployment inventory and RCA docs from infrastructure
consolidation (single K8s atauth instance).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Namespace-scoped kubeconfig and RBAC already provisioned on
the cluster. Doc covers connection setup, deployment architecture,
env vars, common operations, CI/CD, and gotchas.
Namespace-scoped kubeconfig and RBAC already provisioned on
the cluster. Doc covers connection setup, deployment architecture,
env vars, common operations, CI/CD, and gotchas.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Admin dashboard CSS: gradient background, frosted glass sidebar,
card shadows with hover lifts, consistent 12px border-radius matching
the login modal theme.
README: add screenshots section with placeholders, update clone URL
to GitHub.
- Remove gateway/docker-compose.yaml (superseded by root compose)
- Remove gateway/DEPLOYMENT.md (references deleted k8s/helm dirs)
- Remove gateway/README.md (stale, root README is canonical)
- Remove root .env.example (gateway/.env.example is the complete reference)
- Fix clone URLs and CHANGELOG links: GitHub -> Gitea
- Trim CONTRIBUTING.md to reflect current gateway-focused workflow
The /auth/passkey/authenticate/options endpoint returns
{success, options: {...}} but the login page JS was reading
opts.challenge directly instead of opts.options.challenge,
causing the WebAuthn ceremony to fail with undefined values.
Add String() wrappers on all req.params usages to satisfy Express 5's
string | string[] union type. Restore .gitea/workflows/deploy.yml that
was accidentally removed during FOSS sanitization.
Major upgrades:
- @simplewebauthn/server 10.0.1 -> 13.2.3: migrate to v13 credential
API (nested credential object in registrationInfo, renamed authenticator
param to credential in verifyAuthenticationResponse), move type imports
from retired @simplewebauthn/types to @simplewebauthn/server
- better-sqlite3 11.10.0 -> 12.6.2: SQLite 3.50.2 engine, drop Node 18
Patch/minor updates (via npm update):
- @atproto/oauth-client-node 0.3.13 -> 0.3.17
- cors 2.8.5 -> 2.8.6
- otpauth 9.2.1 -> 9.5.0
- qrcode 1.5.3 -> 1.5.4
Also resolves all 4 npm audit vulnerabilities (qs, undici, ajv, minimatch).
All 394 tests pass.
Use single root-level node_modules/ instead of per-directory patterns.
Prevents stale node_modules from appearing as untracked.
- docker-compose.yml: use env_file instead of individual env vars,
fixing missing OIDC/passkey/MFA config that broke Docker deployments
- README: add prerequisites, verify step, app configuration step,
CORS_ORIGINS to domain config, forward-auth env var instructions,
passkey feature mention
- HOMELAB: update deploy section to match README flow, add all 20
presets, add forward-auth env setup, add CORS troubleshooting
- .env.example: note Docker Compose DB_PATH override
The Quick Start was missing the domain configuration step and how
to expose the service via a reverse proxy. Now walks through all
three steps: configure domain + secrets, start with docker compose,
set up TLS reverse proxy, then open the admin dashboard.
CLAUDE.md and .claude/ are local development tooling and should
not be in the public repository.
Extract project structure, testing guide, and code patterns into
.claude/commands/ skills (/structure, /testing, /patterns). Keep
CLAUDE.md as a lean quick-reference. Fix inflated test count
(394 actual, not 827 which included dist/ duplicates).
- Add CLAUDE.md development guide (project structure, testing, gotchas)
- Update README with 10 new OIDC presets (22 total)
- Add CHANGELOG v2.2.0 entry
- Update SECURITY.md supported versions for v2.x
- Add audit_log table and admin operation logging
- Add GET /admin/audit-log endpoint
- Validate CORS wildcard at startup, limit body size to 16kb
- Validate email format on removal, handle format on proxy auth
Add tests for OIDC revocation (RFC 7009), logout/end_session,
userinfo endpoint, and passkey service (WebAuthn registration,
authentication, credential management). Raises overall coverage
from ~50% to ~56% statements.
Use **/*.test.ts instead of *.test.ts to match test files in
subdirectories during Docker builds.
Bump gateway version for v2.2.0 release. Include unit tests for
rate limiting, session management, token handling, error utilities,
and HMAC verification.
Remove infrastructure-specific files (.claude/, CLAUDE.md, .gitea/,
SAFE-DEPLOY.md). Replace private domains with example.com in tests,
docs, and comments. Update clone URLs to GitHub.
OAuthResolverError was falling through to the generic 500 handler,
giving users no useful feedback when they mistyped their handle.
Now returns 400 with specific guidance about DNS records or handle
spelling.
Paperless-ngx, Vaultwarden, Miniflux, Mattermost, Vikunja,
Plane, GoToSocial, Stirling-PDF, Tandoor Recipes, FreshRSS.
Brings total wizard presets from 10 to 20. Each includes
verified redirect URI, PKCE/auth method settings, and
step-by-step setup instructions from official documentation.
Profile page operations (delete passkey + reload + register + reload)
easily exhaust 10 req/min when combined with normal page loads.
req.protocol returns 'http' behind reverse proxy, causing the
login redirect URL to fail the allowed origins check (403).
residentKey: 'preferred' → 'required' so Firefox stores passkeys
as discoverable credentials. The OIDC login page authenticates
without allowCredentials (user not identified yet), which requires
discoverable credentials to work.
Add self-service profile page at /auth/profile for passkey
registration/management and session management. Refactor login
pages to dark theme with gradient accents, no emojis.
Pins deployment to specific commit SHA tag rather than relying on
:latest tag with rollout restart, which fails when the deployment
image was previously set to a different tag.
- Prefix unused nonce params with _ in proxy-auth.ts render functions
- Remove unused imports (vi, beforeEach, afterEach) from test files
- Use bare catch in admin-dashboard.ts access rule handler
- Remove unused variable in authorize.test.ts
Users with a registered passkey can now sign in via WebAuthn on the
OIDC login page, skipping the Bluesky OAuth round-trip entirely.
- Add POST /oauth/authorize/passkey endpoint
- Wire PasskeyService through to OIDC authorize router
- Add passkey button with inline WebAuthn JS (feature-detected)
- 8 new tests for passkey authorize flow
- Remove hardcoded fallback values for OIDC_KEY_SECRET, MFA_ENCRYPTION_KEY,
and FORWARD_AUTH_SESSION_SECRET; fail-fast validation at startup when
features are enabled
- Escape all user-controlled template interpolations in OIDC login page
(clientName, state, authCode, errorMessage) to prevent XSS
- Replace URL query param secret display with one-time flash tokens
(in-memory Map with 60s TTL, consumed on first access)
- Update nodemailer from v6 to v7 (SES transport security fix)
- Update docker-compose.yaml to use required variable syntax
- Update .env.example with all current configuration options
- Bump version to 2.0.2
Fixes 5 HIGH, 16 MEDIUM, 14 LOW, 8 INFO findings across 7 phases:
- Token revocation blacklist via jti claims in SQLite (H-2)
- Session endpoint auth hardening with gateway token validation (H-1)
- Refresh token scope validation per RFC 6749 Section 6 (M-9)
- Removed plain PKCE from OIDC discovery, S256-only (H-3)
- Passkey challenges moved from in-memory to SQLite (M-4)
- TOTP replay protection via absolute period tracking (M-5)
- Email verification lockout after 5 failed attempts (M-8)
- OAuth PDS sessions moved from in-memory to SQLite (L-1)
- AES-256-GCM IV migration (16->12 bytes) with HKDF key derivation (L-3/L-4)
- JWT kid fallback hardened - reject when kid present but not found (L-2)
- WebAuthn requireUserVerification enforced (M-2)
- Webhook HTML escaping for XSS prevention (M-7)
- CSP form-action directive added (M-6)
- Recovery scope restricted to openid/profile/email (L-7)
- Cache-Control: no-store on token info endpoint (M-1)
- Docker image SHA pinning, compose security hardening (D-2/D-3)
- CI kubeconfig cleanup with mktemp+trap (D-1)
- Rust lib: zeroize secrets on drop, RwLock poison recovery,
removed unused postgres deps, pinned chrono, upgraded rusqlite
- OIDC presets: pkce_note documentation for disabled PKCE clients
423 tests passing, 0 npm vulnerabilities.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds /api/pds/write endpoint that proxies authenticated xRPC calls
to users' PDS via their stored OAuth sessions. Whitelists only
createRecord and putRecord for atchess.game and atchess.profile
collections. Validates Bearer token and enforces repo matches DID.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add user-level access gating to OIDC clients and Legacy HMAC apps,
matching the existing forward-auth proxy access control pattern.
- New `client_access_rules` table for per-client allow/deny rules
- New `require_access_check` flag on apps table (default: off)
- Enforcement in OIDC authorize callback + passkey flow
- Enforcement in Legacy HMAC auth callback
- Admin API: CRUD endpoints + dry-run access check
- Generic `checkAccess()` now works with both proxy and client rules
- 19 new tests (423 total, all passing)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add passkey/WebAuthn support to the forward-auth proxy login flow,
previously only available in the OIDC authorize flow:
- New POST /auth/proxy/passkey endpoint
- Passkey button + WebAuthn JS on proxy login page
- 9 new tests for proxy passkey flow
Security fixes from audit:
- MFA verify endpoints require authentication (prevent unauthenticated brute-force)
- Session expiry enforced in database query
- OIDC logout redirect uses origin comparison (prevent open redirect)
- PKCE plain method rejected, S256 uses constant-time comparison
- Empty DID guard in token endpoint
- Handle format validation in OIDC authorize
- trust proxy configured for correct client IP
- user_id NaN validation
- Removed uuid package (use crypto.randomUUID())
Add passkey/WebAuthn support to the forward-auth proxy login flow,
previously only available in the OIDC authorize flow:
- New POST /auth/proxy/passkey endpoint
- Passkey button + WebAuthn JS on proxy login page
- 9 new tests for proxy passkey flow
Security fixes from audit:
- MFA verify endpoints require authentication (prevent unauthenticated brute-force)
- Session expiry enforced in database query
- OIDC logout redirect uses origin comparison (prevent open redirect)
- PKCE plain method rejected, S256 uses constant-time comparison
- Empty DID guard in token endpoint
- Handle format validation in OIDC authorize
- trust proxy configured for correct client IP
- user_id NaN validation
- Removed uuid package (use crypto.randomUUID())
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove gateway/docker-compose.yaml (superseded by root compose)
- Remove gateway/DEPLOYMENT.md (references deleted k8s/helm dirs)
- Remove gateway/README.md (stale, root README is canonical)
- Remove root .env.example (gateway/.env.example is the complete reference)
- Fix clone URLs and CHANGELOG links: GitHub -> Gitea
- Trim CONTRIBUTING.md to reflect current gateway-focused workflow
Major upgrades:
- @simplewebauthn/server 10.0.1 -> 13.2.3: migrate to v13 credential
API (nested credential object in registrationInfo, renamed authenticator
param to credential in verifyAuthenticationResponse), move type imports
from retired @simplewebauthn/types to @simplewebauthn/server
- better-sqlite3 11.10.0 -> 12.6.2: SQLite 3.50.2 engine, drop Node 18
Patch/minor updates (via npm update):
- @atproto/oauth-client-node 0.3.13 -> 0.3.17
- cors 2.8.5 -> 2.8.6
- otpauth 9.2.1 -> 9.5.0
- qrcode 1.5.3 -> 1.5.4
Also resolves all 4 npm audit vulnerabilities (qs, undici, ajv, minimatch).
All 394 tests pass.
- docker-compose.yml: use env_file instead of individual env vars,
fixing missing OIDC/passkey/MFA config that broke Docker deployments
- README: add prerequisites, verify step, app configuration step,
CORS_ORIGINS to domain config, forward-auth env var instructions,
passkey feature mention
- HOMELAB: update deploy section to match README flow, add all 20
presets, add forward-auth env setup, add CORS troubleshooting
- .env.example: note Docker Compose DB_PATH override
- Add CLAUDE.md development guide (project structure, testing, gotchas)
- Update README with 10 new OIDC presets (22 total)
- Add CHANGELOG v2.2.0 entry
- Update SECURITY.md supported versions for v2.x
- Add audit_log table and admin operation logging
- Add GET /admin/audit-log endpoint
- Validate CORS wildcard at startup, limit body size to 16kb
- Validate email format on removal, handle format on proxy auth
Users with a registered passkey can now sign in via WebAuthn on the
OIDC login page, skipping the Bluesky OAuth round-trip entirely.
- Add POST /oauth/authorize/passkey endpoint
- Wire PasskeyService through to OIDC authorize router
- Add passkey button with inline WebAuthn JS (feature-detected)
- 8 new tests for passkey authorize flow
- Remove hardcoded fallback values for OIDC_KEY_SECRET, MFA_ENCRYPTION_KEY,
and FORWARD_AUTH_SESSION_SECRET; fail-fast validation at startup when
features are enabled
- Escape all user-controlled template interpolations in OIDC login page
(clientName, state, authCode, errorMessage) to prevent XSS
- Replace URL query param secret display with one-time flash tokens
(in-memory Map with 60s TTL, consumed on first access)
- Update nodemailer from v6 to v7 (SES transport security fix)
- Update docker-compose.yaml to use required variable syntax
- Update .env.example with all current configuration options
- Bump version to 2.0.2