feat: Add anonymous user authentication with WebAuthn passkey support#16
Conversation
- Implement anonymous user system with UUID-based accounts - Add username/passphrase authentication with SHA-256 hashing - Add WebAuthn/passkey support for passwordless login - Implement passphrase complexity validation with visual indicators - Add group association management for anonymous users - Add account recovery via username + passphrase - Add change passphrase functionality for authenticated users - Add passkey management (generate/remove) for linked accounts - Add sign out vs delete account options with group cleanup choice - Implement IP-based rate limiting (10 req/min) on all endpoints - Add smart persistence (only save accounts with groups or auth) - Add password manager compatibility (1Password, etc.) - Create Prisma schema with AnonymousUser and AnonymousUserGroup models - Add three database migrations for user tables and passkey fields - Position anonymous auth menu in header navigation - Add ANONYMOUS_USER_CHANGES.md documentation Technical details: - Next.js 16 with Turbopack configuration - Prisma 6.18 with PostgreSQL (Neon) - @simplewebauthn/browser and @simplewebauthn/server v10.0.0 - localStorage for client-side auth state - Discoverable credentials for cross-device passkey login - Dynamic WebAuthn rpID/origin derivation for all environments - In-memory rate limiting with automatic cleanup
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a comprehensive anonymous user authentication system with WebAuthn passkey support, allowing users to create anonymous accounts, recover them across devices using username/passphrase, and use passkeys for passwordless authentication. The implementation includes client-side state management, 11 new API endpoints with rate limiting, database schema changes, and a feature-rich UI component.
Changes:
- Added anonymous user authentication system with UUID-based accounts, passphrase recovery, and WebAuthn passkey support
- Implemented IP-based rate limiting (10 req/min) across all 11 anonymous user API endpoints using in-memory storage
- Created database schema for AnonymousUser and AnonymousUserGroup tables with three migrations
Reviewed changes
Copilot reviewed 22 out of 23 changed files in this pull request and generated 28 comments.
Show a summary per file
| File | Description |
|---|---|
| src/lib/rate-limit.ts | In-memory rate limiter with IP-based tracking and probabilistic cleanup |
| src/components/anonymous-auth-menu.tsx | 1028-line React component providing UI for account management, authentication, and group associations |
| src/app/layout.tsx | Integration of AnonymousAuthMenu into application header |
| src/app/groups/recent-groups-helpers.ts | Added setRecentGroups helper for bulk group list updates |
| src/app/api/anonymous-users/ensure/route.ts | Endpoint for creating/updating user records with smart persistence |
| src/app/api/anonymous-users/groups/route.ts | GET/POST endpoints for managing group associations with auto-cleanup |
| src/app/api/anonymous-users/recover/route.ts | Account recovery via username/passphrase authentication |
| src/app/api/anonymous-users/passphrase/route.ts | Passphrase creation and update endpoint |
| src/app/api/anonymous-users/delete/route.ts | Account deletion endpoint |
| src/app/api/anonymous-users/passkey/register-options/route.ts | WebAuthn registration challenge generation |
| src/app/api/anonymous-users/passkey/register-verify/route.ts | WebAuthn registration verification and credential storage |
| src/app/api/anonymous-users/passkey/auth-options/route.ts | WebAuthn authentication challenge generation |
| src/app/api/anonymous-users/passkey/auth-verify/route.ts | WebAuthn authentication verification |
| src/app/api/anonymous-users/passkey/delete/route.ts | Passkey removal endpoint |
| prisma/schema.prisma | Added AnonymousUser and AnonymousUserGroup models with relations to Group |
| prisma/migrations/* | Three migrations adding tables and fields for anonymous users and passkeys |
| package.json | Added @simplewebauthn/browser and @simplewebauthn/server dependencies |
| next.config.mjs | Added Turbopack root configuration |
| ANONYMOUS_USER_CHANGES.md | Comprehensive documentation of implementation and data hygiene approach |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const user = await prisma.anonymousUser.findUnique({ | ||
| where: { | ||
| username: body.username, | ||
| passphraseHash: body.passphraseHash, | ||
| }, | ||
| include: { groups: true }, | ||
| }) |
There was a problem hiding this comment.
The findUnique query uses composite fields (username and passphraseHash) but Prisma's findUnique only works with fields that have a unique constraint. In the schema, username and passphraseHash have separate unique constraints, but there's no composite unique constraint on both fields together. This query should use findFirst instead to avoid runtime errors.
| try { | ||
| await prisma.anonymousUser.delete({ | ||
| where: { id: body.id }, | ||
| }) |
There was a problem hiding this comment.
The account deletion endpoint allows any user to delete any account by simply knowing the userId. There's no authentication check to verify that the requester owns the account they're trying to delete. An attacker who discovers or guesses a user's UUID could permanently delete their account and all associated data. Add proper authorization checks to ensure only the account owner can delete their account.
|
@copilot open a new pull request to apply changes based on the comments in this thread |
…ported the type to satisfy generateAuthenticationOptions
omitted transports from allowCredentials, which resolves the compile error while keeping the flow intact
Installed latest baseline-browser-mapping (package.json and package-lock.json updated
…ing userId and username
…ions (#17) * Initial plan * Address code review comments - error handling, validation, and type fixes Co-authored-by: carnach <26198260+carnach@users.noreply.github.com> * Add documentation, improve error messages, and enforce passphrase complexity Co-authored-by: carnach <26198260+carnach@users.noreply.github.com> * Add security review notes documenting remaining architectural concerns Co-authored-by: carnach <26198260+carnach@users.noreply.github.com> * Add environment variable validation in security documentation Co-authored-by: carnach <26198260+carnach@users.noreply.github.com> * Fixed the error by selecting passkeyTransports in the query so it can be referenced. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: carnach <26198260+carnach@users.noreply.github.com> Co-authored-by: carnach <carnach@users.noreply.github.com> Co-authored-by: carnach <gevert@gmail.com>
Anonymous User Authentication with WebAuthn Passkey Support
🎯 Overview
This PR introduces a comprehensive anonymous user authentication system that allows users to:
✨ Features
1. Anonymous User System
2. Authentication Methods
Username + Passphrase
WebAuthn Passkeys
3. Group Management
4. Account Management
5. Security & Abuse Prevention
🏗️ Technical Implementation
Frontend Components
src/components/anonymous-auth-menu.tsx) - Main UI component (1028 lines)Backend API Routes
All routes under
src/app/api/anonymous-users/:POST /ensure- Create/update user recordGET /groups- Fetch user's associated groupsPOST /groups- Update group associations (with auto-cleanup)POST /passphrase- Create/update passphrasePOST /recover- Recover account by username/passphrasePOST /delete- Delete account permanentlyPasskey endpoints under
src/app/api/anonymous-users/passkey/:POST /register-options- Generate WebAuthn registration challengePOST /register-verify- Verify and store passkey credentialPOST /auth-options- Generate authentication challengePOST /auth-verify- Verify passkey authenticationPOST /delete- Remove passkey from accountDatabase Schema
Migrations
Three database migrations applied:
20260201111211_add_anonymous_users- Initial user and group tables20260201112137_add_anonymous_usernames- Add username field with unique constraint20260201114517_add_passkey_support- Add WebAuthn passkey fieldsDependencies Added
{ "@simplewebauthn/browser": "^10.0.0", "@simplewebauthn/server": "^10.0.1" }Configuration Updates
dev:vercelscript for Vercel CLI development🔒 Security Considerations
Implemented
✅ SHA-256 passphrase hashing (client-side before transmission)
✅ IP-based rate limiting on all endpoints
✅ Unique constraints on username and passphraseHash
✅ WebAuthn challenge validation
✅ Dynamic rpID/origin derivation for all environments
✅ No sensitive data in localStorage (only UUIDs)
✅ Cascade deletion for user groups
✅ Password manager compatibility with proper autocomplete attributes
Considerations
📊 Data Hygiene
The system implements smart persistence to prevent database bloat:
New users are NOT saved to database until they:
Existing users are automatically deleted when:
Rate limiting prevents abuse and spam account creation
🧪 Testing Recommendations
Manual Testing Checklist
Database Testing
Cross-Device Testing
📸 Screenshots
Anonymous Auth Menu (Dropdown)

Account Creation/Recovery

Passphrase Complexity Indicators

Passkey Management

Sign Out Options

📝 Documentation
🔄 Breaking Changes
None. This is a new feature that doesn't affect existing functionality.
🚀 Deployment Considerations
npm installto add WebAuthn libraries📋 Checklist
🔗 Related Issues
Closes #[issue-number] (if applicable)
👥 Reviewers
Please pay special attention to:
Ready for review! 🎉