v0.1.3
Client-side passkey authentication package with React hook
A complete, production-ready passkey (WebAuthn) authentication system with client package, serverless API, and comprehensive documentation.
passkey/ ├── package/ # @passkey/client - Client-side library │ ├── src/ │ └── README.md ├── api/ # @passkey/api - Serverless API │ ├── src/ │ └── README.md └── docs/ # Documentation ├── api-reference.md ├── guide-with-api.md └── guide-without-api.md
Perfect for serverless deployments and quick prototyping.
Install and run the API:
cd api npm install cp .env.example .env.local npm run dev
Install the client package in your app:
npm install @passkey/client
Use in your React app:
import { usePasskey } from '@passkey/client'; function LoginPage() { const { register, authenticate, isLoading } = usePasskey(); const handleRegister = async () => { const result = await register('user@example.com', 'John Doe'); if (result.success) { console.log('Registered!'); } }; const handleLogin = async () => { const result = await authenticate('user@example.com'); if (result.success) { console.log('Logged in!'); } }; return ( <div> <button onClick={handleRegister} disabled={isLoading}> Register </button> <button onClick={handleLogin} disabled={isLoading}> Login </button> </div> ); }
📖 Full Guide: Using the Included API
Perfect for existing projects with established backends.
Install the client package:
npm install @passkey/client
Implement 4 API endpoints in your backend:
POST /register/optionsPOST /register/verifyPOST /authenticate/optionsPOST /authenticate/verifyConnect the client to your API:
const { register, authenticate } = usePasskey({ apiUrl: 'https://your-api.com/passkey' });
Client-side library for passkey authentication with React hook support.
npm install @passkey/client
Features:
usePasskey)PasskeyClient)Serverless API for passkey authentication built with Next.js.
cd api npm install npm run dev
Features:
# Install all workspace dependencies npm install # Install specific workspace npm install --workspace=package npm install --workspace=api
# Build all packages npm run build # Build specific package npm run build --workspace=package
# API server npm run dev:api # Package (watch mode) npm run dev:package
Passkeys require WebAuthn support:
| Browser | Version |
|---|---|
| Chrome/Edge | 67+ |
| Firefox | 60+ |
| Safari | 13+ |
This system is configured to work with modern passkey implementations and WebAuthn-compatible authenticators. In practice, this means users can:
Note that passkeys generally do not sync between different ecosystems (for example, a passkey created in iCloud Keychain on a Mac cannot automatically be used on an unrelated Android device that only uses Google Password Manager). For true cross-platform use across ecosystems, users can instead use cross-platform authenticators such as compatible hardware security keys.
The system uses residentKey: "required" to create resident (discoverable) credentials, which enables usernameless / account-selection flows on supported authenticators. This setting controls how credentials are stored and discovered on the authenticator; it does not itself provide cross-ecosystem syncing.
This system implements WebAuthn best practices:
Production Checklist:
RP_ID and ORIGINcd api vercel
Set environment variables:
RP_NAME - Your app nameRP_ID - Your domain (e.g., myapp.com)ORIGIN - Your full URL (e.g., https://myapp.com)cd api netlify deploy --prod
The API works on any platform supporting Next.js:
Contributions are welcome! Please feel free to submit a Pull Request.
MIT
import { usePasskey } from '@passkey/client'; import { useState } from 'react'; export function PasskeyAuth() { const [email, setEmail] = useState(''); const { register, authenticate, isLoading, error, isSupported } = usePasskey(); if (!isSupported) { return <div>Passkeys not supported in this browser</div>; } return ( <div> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" /> <button onClick={() => register(email, email)} disabled={isLoading} > Register </button> <button onClick={() => authenticate(email)} disabled={isLoading} > Login </button> {error && <p>{error}</p>} </div> ); }
import { PasskeyClient } from '@passkey/client'; const client = new PasskeyClient({ apiUrl: '/api/passkey' }); // Register const registerResult = await client.register( 'user@example.com', 'John Doe' ); // Authenticate const authResult = await client.authenticate('user@example.com');
'use client'; import { usePasskey } from '@passkey/client'; export default function LoginPage() { const passkey = usePasskey({ apiUrl: '/api/passkey' }); return ( <main> <h1>Login with Passkey</h1> <button onClick={() => passkey.register('user@example.com', 'User')}> Register </button> <button onClick={() => passkey.authenticate('user@example.com')}> Login </button> </main> ); }
Q: Do I need to use the included API?
A: No, you can use your own backend. The client package works with any API that implements the WebAuthn protocol.
Q: Can I use this with Next.js App Router?
A: Yes! The usePasskey hook works in client components. Just add 'use client' directive.
Q: How do I store credentials in a database?
A: Implement the PasskeyStorage interface and pass it to PasskeyService. See the guides for examples.
Q: Is this production-ready?
A: Yes, but replace the in-memory storage with a proper database and implement session management.
Q: Can users have multiple passkeys?
A: Yes, the system supports multiple credentials per user.
Q: What about account recovery?
A: Implement email-based recovery or allow multiple passkeys. See the guides for examples.
Choose your path: