mulguard 1.0.1 โ†’ 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,93 +1,201 @@
1
- # Mukey - Modern Authentication Library
1
+ # Mulguard
2
2
 
3
- > Backend-first authentication library for Next.js and modern web applications
3
+ > A modern, backend-first authentication library for Next.js applications
4
4
 
5
- [![License](https://img.shields.io/badge/license-MUV-blue.svg)](LICENSE)
5
+ [![License: MUV](https://img.shields.io/badge/License-MUV-blue.svg)](LICENSE)
6
6
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.3+-blue.svg)](https://www.typescriptlang.org/)
7
+ [![Next.js](https://img.shields.io/badge/Next.js-14.0+-black.svg)](https://nextjs.org/)
7
8
 
8
- Mukey is a modern, secure authentication library designed for Next.js applications with a backend-first architecture. It provides a simple API similar to `better-auth` and `auth.js`, while maintaining full control over your backend authentication logic.
9
+ **Mulguard** is a powerful, flexible authentication library designed specifically for Next.js applications. Built with a backend-first architecture, it gives you complete control over your authentication logic while providing a simple, intuitive API similar to popular libraries like `better-auth` and `auth.js`.
10
+
11
+ **Part of the [Mulverse](https://mulverse.com) ecosystem** - Empowering modern web applications with robust, secure authentication.
12
+
13
+ ---
14
+
15
+ ## Table of Contents
16
+
17
+ - [Features](#-features)
18
+ - [Installation](#-installation)
19
+ - [Quick Start](#-quick-start)
20
+ - [Core Concepts](#-core-concepts)
21
+ - [Authentication Methods](#-authentication-methods)
22
+ - [Configuration](#-configuration)
23
+ - [Server-Side Usage](#-server-side-usage)
24
+ - [Client-Side Usage](#-client-side-usage)
25
+ - [Components](#-components)
26
+ - [Security](#-security)
27
+ - [Backend Integration](#-backend-integration)
28
+ - [Advanced Features](#-advanced-features)
29
+ - [API Reference](#-api-reference)
30
+ - [Examples](#-examples)
31
+ - [Testing](#-testing)
32
+ - [Contributing](#-contributing)
33
+ - [License](#-license)
34
+ - [Support](#-support)
35
+
36
+ ---
9
37
 
10
38
  ## โœจ Features
11
39
 
12
- - ๐Ÿ” **Multiple Auth Methods**
13
- - Email/Password authentication
14
- - OAuth 2.1 (Google, GitHub, etc.)
15
- - PassKey/WebAuthn support
16
- - Two-Factor Authentication (2FA/TOTP)
17
-
18
- - ๐ŸŽฏ **Account Picker**
19
- - Remember last logged-in users
20
- - Quick re-login experience
21
- - Encrypted local storage
22
-
23
- - ๐Ÿ”’ **Security First**
24
- - CSRF protection
25
- - XSS prevention
26
- - Input validation & sanitization
27
- - Security headers
28
- - Rate limiting utilities
29
-
30
- - โšก **Next.js Optimized**
31
- - Server Components support
32
- - Client hooks (`useAuth`, `useSession`)
33
- - Middleware integration
34
- - API route handlers
35
-
36
- - ๐Ÿ”Œ **Backend-First**
37
- - No database adapter required
38
- - Works with your existing backend API
39
- - Mulink integration support
40
- - Full TypeScript support
40
+ ### ๐Ÿ” Multiple Authentication Methods
41
+ - **Email/Password** - Traditional credential-based authentication
42
+ - **OAuth 2.1** - Support for Google, GitHub, and other OAuth providers
43
+ - **PassKey/WebAuthn** - Passwordless authentication with biometric support
44
+ - **Two-Factor Authentication (2FA/TOTP)** - Time-based one-time passwords with backup codes
45
+ - **OTP** - One-time password authentication
46
+
47
+ ### ๐ŸŽฏ Account Picker
48
+ - Remember last logged-in users
49
+ - Quick re-login experience
50
+ - Encrypted local storage for security
51
+ - Configurable account limits
52
+
53
+ ### ๐Ÿ”’ Security First
54
+ - **CSRF Protection** - Token-based cross-site request forgery protection
55
+ - **XSS Prevention** - Input sanitization and HTML escaping
56
+ - **Security Headers** - Automatic security headers configuration
57
+ - **Input Validation** - Comprehensive validation and sanitization
58
+ - **Rate Limiting** - Built-in rate limiting utilities
59
+ - **Secure Cookies** - HttpOnly, Secure, SameSite cookie configuration
60
+
61
+ ### โšก Next.js Optimized
62
+ - **Server Components** - Full support for React Server Components
63
+ - **Client Hooks** - `useAuth`, `useSession` for client-side state management
64
+ - **Middleware Integration** - Seamless Next.js middleware support
65
+ - **API Route Handlers** - Pre-built route handlers for authentication endpoints
66
+ - **Server Actions** - Native support for Next.js Server Actions
67
+
68
+ ### ๐Ÿ”Œ Backend-First Architecture
69
+ - **No Database Adapter Required** - Works with your existing backend API
70
+ - **Custom Actions** - Implement your own authentication logic
71
+ - **Flexible Integration** - Works with any backend (REST, GraphQL, etc.)
72
+ - **Mulink Integration** - Optional integration with Mulink API client
73
+ - **Full TypeScript Support** - Complete type safety throughout
74
+
75
+ ---
41
76
 
42
77
  ## ๐Ÿ“ฆ Installation
43
78
 
44
79
  ```bash
45
- npm install mukey
80
+ npm install mulguard
46
81
  ```
47
82
 
83
+ ### Peer Dependencies
84
+
85
+ Mulguard requires the following peer dependencies:
86
+
87
+ ```bash
88
+ npm install next@>=14.0.0 react@>=18.0.0 react-dom@>=18.0.0
89
+ ```
90
+
91
+ ---
92
+
48
93
  ## ๐Ÿš€ Quick Start
49
94
 
50
95
  ### 1. Create Auth Configuration
51
96
 
52
- ```typescript
53
- // lib/auth.ts
54
- import { mukey } from 'mukey'
55
- // import { apiClient } from '@mulink/client' // Optional: Use Mulink
97
+ Create a new file `lib/auth.ts`:
56
98
 
57
- export const auth = mukey({
58
- // Option 1: Use Mulink API client
59
- // apiClient: apiClient,
99
+ ```typescript
100
+ import { mulguard } from 'mulguard'
101
+ import type { EmailCredentials, AuthResult, Session } from 'mulguard'
102
+ import { db } from '@/lib/db'
103
+ import { comparePassword } from '@/lib/password'
60
104
 
61
- // Option 2: Use baseURL
62
- baseURL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001',
63
-
105
+ export const auth = mulguard({
106
+ // Session configuration
64
107
  session: {
65
- cookieName: '__mukey_session',
108
+ cookieName: '__mulguard_session',
66
109
  expiresIn: 60 * 60 * 24 * 7, // 7 days
110
+ httpOnly: true,
111
+ secure: process.env.NODE_ENV === 'production', // HTTPS only in production
112
+ sameSite: 'lax',
113
+ },
114
+
115
+ // Required: Implement your authentication actions
116
+ actions: {
117
+ signIn: {
118
+ // โœ… Unified interface: auth.signIn('credentials', {...}) or auth.signIn.email({...})
119
+ email: async (credentials: EmailCredentials): Promise<AuthResult> => {
120
+ // Your custom sign-in logic
121
+ const user = await db.user.findUnique({
122
+ where: { email: credentials.email }
123
+ })
124
+
125
+ if (!user || !await comparePassword(credentials.password, user.password)) {
126
+ return {
127
+ success: false,
128
+ error: 'Invalid credentials',
129
+ errorCode: 'INVALID_CREDENTIALS'
130
+ }
131
+ }
132
+
133
+ const session: Session = {
134
+ user: {
135
+ id: user.id,
136
+ email: user.email,
137
+ name: user.name,
138
+ emailVerified: user.emailVerified,
139
+ },
140
+ expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
141
+ }
142
+
143
+ return { success: true, user: session.user, session }
144
+ },
145
+ },
146
+
147
+ getSession: async (): Promise<Session | null> => {
148
+ // Your custom session retrieval logic
149
+ // Can read from cookie or database
150
+ return await db.getSession()
151
+ },
152
+
153
+ signOut: async () => {
154
+ // Your custom sign-out logic
155
+ await db.invalidateSession()
156
+ return { success: true }
157
+ },
67
158
  },
68
159
 
160
+ // Optional: OAuth providers (auto-generates OAuth actions)
69
161
  providers: {
70
162
  oauth: {
71
163
  google: {
72
164
  clientId: process.env.GOOGLE_CLIENT_ID!,
165
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET, // Server-side only
73
166
  redirectUri: `${process.env.NEXT_PUBLIC_URL}/api/auth/callback/google`,
74
167
  scopes: ['openid', 'profile', 'email'],
75
168
  },
169
+ github: {
170
+ clientId: process.env.GITHUB_CLIENT_ID!,
171
+ clientSecret: process.env.GITHUB_CLIENT_SECRET,
172
+ redirectUri: `${process.env.NEXT_PUBLIC_URL}/api/auth/callback/github`,
173
+ scopes: ['user:email'],
174
+ },
76
175
  },
77
176
  },
78
177
 
79
- accountPicker: {
80
- enabled: true,
81
- maxAccounts: 3,
178
+ // Optional: Callbacks for lifecycle events
179
+ callbacks: {
180
+ onSignIn: async (user, session) => {
181
+ // Track sign-in analytics, update last login, etc.
182
+ console.log('User signed in:', user.email)
183
+ },
184
+ onError: async (error, context) => {
185
+ // Log errors for monitoring
186
+ console.error(`Auth error in ${context}:`, error)
187
+ },
82
188
  },
83
189
  })
84
190
  ```
85
191
 
192
+ > ๐Ÿ“– **For a complete guide with best practices**, see [GUIDE.md](./GUIDE.md)
193
+
86
194
  ### 2. Server-Side Usage
87
195
 
88
196
  ```typescript
89
197
  // app/dashboard/page.tsx
90
- import { getServerSession } from 'mukey/server'
198
+ import { getServerSession } from 'mulguard/server'
91
199
  import { auth } from '@/lib/auth'
92
200
  import { redirect } from 'next/navigation'
93
201
 
@@ -98,7 +206,12 @@ export default async function DashboardPage() {
98
206
  redirect('/login')
99
207
  }
100
208
 
101
- return <div>Welcome, {session.user.name}!</div>
209
+ return (
210
+ <div>
211
+ <h1>Welcome, {session.user.name}!</h1>
212
+ <p>Email: {session.user.email}</p>
213
+ </div>
214
+ )
102
215
  }
103
216
  ```
104
217
 
@@ -108,7 +221,7 @@ export default async function DashboardPage() {
108
221
  // app/login/page.tsx
109
222
  'use client'
110
223
 
111
- import { useAuth } from 'mukey/client'
224
+ import { useAuth } from 'mulguard/client'
112
225
  import { auth } from '@/lib/auth'
113
226
  import { useState } from 'react'
114
227
 
@@ -119,9 +232,19 @@ export default function LoginPage() {
119
232
 
120
233
  const handleSubmit = async (e: React.FormEvent) => {
121
234
  e.preventDefault()
122
- const result = await signIn.email({ email, password })
235
+
236
+ // โœ… Unified interface (recommended)
237
+ const result = await signIn('credentials', { email, password })
238
+
239
+ // Or use direct method:
240
+ // const result = await signIn.email({ email, password })
241
+
123
242
  if (result.success) {
124
243
  // Redirect to dashboard
244
+ window.location.href = '/dashboard'
245
+ } else {
246
+ // Handle error
247
+ alert(result.error)
125
248
  }
126
249
  }
127
250
 
@@ -135,12 +258,14 @@ export default function LoginPage() {
135
258
  value={email}
136
259
  onChange={(e) => setEmail(e.target.value)}
137
260
  placeholder="Email"
261
+ required
138
262
  />
139
263
  <input
140
264
  type="password"
141
265
  value={password}
142
266
  onChange={(e) => setPassword(e.target.value)}
143
267
  placeholder="Password"
268
+ required
144
269
  />
145
270
  <button type="submit">Sign In</button>
146
271
  </form>
@@ -152,7 +277,7 @@ export default function LoginPage() {
152
277
 
153
278
  ```typescript
154
279
  // middleware.ts
155
- import { createAuthMiddleware } from 'mukey/middleware'
280
+ import { createAuthMiddleware } from 'mulguard/middleware'
156
281
  import { auth } from '@/lib/auth'
157
282
 
158
283
  export default createAuthMiddleware(auth, {
@@ -160,44 +285,191 @@ export default createAuthMiddleware(auth, {
160
285
  redirectTo: '/login',
161
286
  redirectIfAuthenticated: '/dashboard',
162
287
  })
288
+
289
+ export const config = {
290
+ matcher: ['/dashboard/:path*', '/profile/:path*'],
291
+ }
163
292
  ```
164
293
 
165
- ## ๐Ÿ“š Documentation
294
+ ---
295
+
296
+ ## ๐ŸŽ“ Core Concepts
297
+
298
+ ### Backend-First Architecture
299
+
300
+ Mulguard follows a **backend-first** approach, meaning you implement your own authentication logic through **actions**. This gives you:
166
301
 
167
- - [Getting Started](./docs/GETTING_STARTED.md)
168
- - [Authentication Methods](./docs/AUTH_METHODS.md)
169
- - [Server-Side Usage](./docs/SERVER_USAGE.md)
170
- - [Client-Side Usage](./docs/CLIENT_USAGE.md)
171
- - [Security](./docs/SECURITY.md)
172
- - [Backend Integration](./docs/BACKEND_INTEGRATION.md)
173
- - [API Reference](./docs/API_REFERENCE.md)
302
+ - **Full Control** - Complete control over your authentication flow
303
+ - **Flexibility** - Works with any backend architecture
304
+ - **No Lock-in** - No database adapter required
305
+ - **Custom Logic** - Implement business-specific authentication rules
174
306
 
175
- ## ๐Ÿ”ง Configuration
307
+ ### Actions
308
+
309
+ Actions are functions you provide to handle authentication operations:
310
+
311
+ ```typescript
312
+ actions: {
313
+ signIn: {
314
+ email: async (credentials) => { /* ... */ },
315
+ oauth: async (provider) => { /* ... */ },
316
+ passkey: async (options) => { /* ... */ },
317
+ },
318
+ signUp: async (data) => { /* ... */ },
319
+ signOut: async () => { /* ... */ },
320
+ getSession: async () => { /* ... */ },
321
+ // ... more actions
322
+ }
323
+ ```
324
+
325
+ ### Sessions
326
+
327
+ Sessions are stored in HTTP-only cookies and contain:
328
+
329
+ ```typescript
330
+ interface Session {
331
+ user: {
332
+ id: string
333
+ email: string
334
+ name?: string
335
+ avatar?: string
336
+ emailVerified?: boolean
337
+ }
338
+ expiresAt: Date
339
+ accessToken?: string
340
+ refreshToken?: string
341
+ tokenType?: string
342
+ expiresIn?: number
343
+ }
344
+ ```
345
+
346
+ ---
347
+
348
+ ## ๐Ÿ” Authentication Methods
349
+
350
+ ### Unified Sign-In Interface
351
+
352
+ Mulguard provides a **unified interface** for all authentication methods, similar to auth.js:
353
+
354
+ ```typescript
355
+ // โœ… Unified interface (recommended)
356
+ await auth.signIn('credentials', { email: 'user@example.com', password: 'password123' })
357
+ await auth.signIn('google')
358
+ await auth.signIn('otp', { email: 'user@example.com', code: '123456' })
359
+ await auth.signIn('passkey', { userId: 'user-id' })
360
+
361
+ // โœ… Direct methods (for backward compatibility)
362
+ await auth.signIn.email({ email: 'user@example.com', password: 'password123' })
363
+ await auth.signIn.oauth('google')
364
+ await auth.signIn.otp('user@example.com', '123456')
365
+ ```
366
+
367
+ ### Email/Password Authentication
368
+
369
+ ```typescript
370
+ // Using unified interface
371
+ const result = await auth.signIn('credentials', {
372
+ email: 'user@example.com',
373
+ password: 'password123',
374
+ })
375
+
376
+ // Or using direct method
377
+ const result = await auth.signIn.email({
378
+ email: 'user@example.com',
379
+ password: 'password123',
380
+ })
381
+
382
+ if (result.success) {
383
+ console.log('Signed in:', result.user)
384
+ } else {
385
+ console.error('Error:', result.error, result.errorCode)
386
+ }
387
+ ```
388
+
389
+ ### OAuth Authentication
390
+
391
+ ```typescript
392
+ // Initiate OAuth flow (unified interface)
393
+ const { url } = await auth.signIn('google')
394
+ window.location.href = url
395
+
396
+ // Or using direct method
397
+ const { url } = await auth.signIn.oauth('google')
398
+ window.location.href = url
399
+
400
+ // Handle callback (in your API route)
401
+ const result = await auth.oauthCallback(provider, code, state)
402
+
403
+ // โœ… OAuth providers are auto-configured when you add them to providers.oauth
404
+ // No need to implement oauth action manually!
405
+ ```
406
+
407
+ ### PassKey/WebAuthn Authentication
408
+
409
+ ```typescript
410
+ // Register PassKey
411
+ const result = await auth.passkey.register({
412
+ name: 'My iPhone',
413
+ userId: 'user-id',
414
+ })
415
+
416
+ // Authenticate with PassKey
417
+ const result = await auth.signIn.passkey({ userId: 'user-id' })
418
+ ```
419
+
420
+ ### Two-Factor Authentication (2FA)
421
+
422
+ ```typescript
423
+ // Enable 2FA
424
+ const enableResult = await auth.twoFactor.enable()
425
+ // Display QR code to user
426
+
427
+ // Verify 2FA code
428
+ const verifyResult = await auth.twoFactor.verify('123456')
429
+
430
+ // Check if 2FA is enabled
431
+ const isEnabled = await auth.twoFactor.isEnabled()
432
+ ```
433
+
434
+ ---
435
+
436
+ ## โš™๏ธ Configuration
176
437
 
177
438
  ### Full Configuration Options
178
439
 
179
440
  ```typescript
180
- import { mukey } from 'mukey'
441
+ import { mulguard } from 'mulguard'
181
442
 
182
- export const auth = mukey({
183
- // API Client (from Mulink) or baseURL
184
- apiClient: apiClient, // Optional
185
- baseURL: 'http://localhost:3001', // Required if apiClient not provided
186
-
443
+ export const auth = mulguard({
187
444
  // Session configuration
188
445
  session: {
189
- cookieName: '__mukey_session',
446
+ cookieName: '__mulguard_session',
190
447
  expiresIn: 60 * 60 * 24 * 7, // 7 days in seconds
191
448
  httpOnly: true,
192
449
  secure: process.env.NODE_ENV === 'production',
193
450
  sameSite: 'lax',
451
+ path: '/',
452
+ domain: undefined,
453
+ cacheTtl: 5000, // Session cache TTL in milliseconds
194
454
  },
195
455
 
196
- // OAuth providers
456
+ // Required: Authentication actions
457
+ actions: {
458
+ signIn: {
459
+ email: async (credentials) => { /* ... */ },
460
+ // Optional: oauth, passkey, otp
461
+ },
462
+ getSession: async () => { /* ... */ },
463
+ signOut: async () => { /* ... */ },
464
+ // Optional: signUp, resetPassword, verifyEmail, refreshSession, etc.
465
+ },
466
+
467
+ // Optional: OAuth providers
197
468
  providers: {
198
469
  oauth: {
199
470
  google: {
200
471
  clientId: '...',
472
+ clientSecret: '...', // Server-side only
201
473
  redirectUri: '...',
202
474
  scopes: ['openid', 'profile', 'email'],
203
475
  name: 'Google',
@@ -210,20 +482,20 @@ export const auth = mukey({
210
482
  },
211
483
  },
212
484
 
213
- // 2FA configuration
485
+ // Optional: Two-Factor Authentication
214
486
  twoFactor: {
215
487
  enabled: true,
216
488
  },
217
489
 
218
- // Account Picker
490
+ // Optional: Account Picker
219
491
  accountPicker: {
220
492
  enabled: true,
221
493
  maxAccounts: 3,
222
494
  encryptStorage: true,
223
- storageKey: '__mukey_accounts',
495
+ storageKey: '__mulguard_accounts',
224
496
  },
225
497
 
226
- // Security
498
+ // Optional: Security settings
227
499
  security: {
228
500
  csrfProtection: true,
229
501
  rateLimiting: {
@@ -231,15 +503,134 @@ export const auth = mukey({
231
503
  windowMs: 15 * 60 * 1000, // 15 minutes
232
504
  },
233
505
  },
506
+
507
+ // Optional: Callbacks
508
+ callbacks: {
509
+ onSignIn: async (user, session) => {
510
+ // Called after successful sign-in
511
+ },
512
+ onSignOut: async (user) => {
513
+ // Called after sign-out
514
+ },
515
+ onSessionExpired: async (session) => {
516
+ // Called when session expires
517
+ },
518
+ onError: async (error, context) => {
519
+ // Called on authentication errors
520
+ },
521
+ },
522
+
523
+ // Optional: Token refresh configuration
524
+ tokenRefresh: {
525
+ enabled: true,
526
+ refreshThreshold: 300, // 5 minutes before expiration
527
+ maxRetries: 0,
528
+ retryDelay: 1000,
529
+ rateLimit: 1, // 1 attempt per minute
530
+ autoSignOutOnFailure: true,
531
+ redirectToLogin: '/login',
532
+ },
234
533
  })
235
534
  ```
236
535
 
536
+ ---
537
+
538
+ ## ๐Ÿ–ฅ๏ธ Server-Side Usage
539
+
540
+ ### Get Server Session
541
+
542
+ ```typescript
543
+ import { getServerSession } from 'mulguard/server'
544
+ import { auth } from '@/lib/auth'
545
+
546
+ // In Server Components
547
+ const session = await getServerSession(auth)
548
+
549
+ // In API Routes
550
+ export async function GET(request: Request) {
551
+ const session = await getServerSession(auth)
552
+ if (!session) {
553
+ return new Response('Unauthorized', { status: 401 })
554
+ }
555
+ return Response.json({ user: session.user })
556
+ }
557
+ ```
558
+
559
+ ### Server Actions
560
+
561
+ ```typescript
562
+ 'use server'
563
+
564
+ import { auth } from '@/lib/auth'
565
+
566
+ export async function signInAction(email: string, password: string) {
567
+ const result = await auth.signIn.email({ email, password })
568
+ return result
569
+ }
570
+ ```
571
+
572
+ ### API Route Handlers
573
+
574
+ ```typescript
575
+ // app/api/auth/[...mulguard]/route.ts
576
+ import { createAuthHandler } from 'mulguard/handlers/route'
577
+ import { auth } from '@/lib/auth'
578
+
579
+ export const { GET, POST } = createAuthHandler(auth)
580
+ ```
581
+
582
+ ---
583
+
584
+ ## ๐Ÿ’ป Client-Side Usage
585
+
586
+ ### React Hooks
587
+
588
+ ```typescript
589
+ 'use client'
590
+
591
+ import { useAuth, useSession } from 'mulguard/client'
592
+ import { auth } from '@/lib/auth'
593
+
594
+ export function AuthComponent() {
595
+ const { signIn, signOut, isLoading } = useAuth(auth)
596
+ const { session, isLoading: sessionLoading } = useSession(auth)
597
+
598
+ // Use hooks...
599
+ }
600
+ ```
601
+
602
+ ### Mulguard Provider
603
+
604
+ ```typescript
605
+ // app/layout.tsx
606
+ 'use client'
607
+
608
+ import { MulguardProvider } from 'mulguard/client'
609
+ import { auth } from '@/lib/auth'
610
+
611
+ export default function RootLayout({ children }) {
612
+ return (
613
+ <html>
614
+ <body>
615
+ <MulguardProvider auth={auth}>
616
+ {children}
617
+ </MulguardProvider>
618
+ </body>
619
+ </html>
620
+ )
621
+ }
622
+ ```
623
+
624
+ > **Note:** `AuthProvider` is still available for backward compatibility but is deprecated. Use `MulguardProvider` instead.
625
+
626
+ ---
627
+
237
628
  ## ๐ŸŽจ Components
238
629
 
239
630
  ### Account Picker
240
631
 
241
632
  ```typescript
242
- import { AccountPicker } from 'mukey'
633
+ import { AccountPicker } from 'mulguard'
243
634
 
244
635
  <AccountPicker
245
636
  auth={auth}
@@ -256,7 +647,7 @@ import { AccountPicker } from 'mukey'
256
647
  ### OAuth Button
257
648
 
258
649
  ```typescript
259
- import { OAuthButton } from 'mukey'
650
+ import { OAuthButton } from 'mulguard'
260
651
 
261
652
  <OAuthButton
262
653
  auth={auth}
@@ -264,13 +655,18 @@ import { OAuthButton } from 'mukey'
264
655
  onSuccess={() => {
265
656
  // Handle success
266
657
  }}
267
- />
658
+ onError={(error) => {
659
+ // Handle error
660
+ }}
661
+ >
662
+ Sign in with Google
663
+ </OAuthButton>
268
664
  ```
269
665
 
270
- ### 2FA Setup
666
+ ### Two-Factor Setup
271
667
 
272
668
  ```typescript
273
- import { TwoFactorSetup } from 'mukey'
669
+ import { TwoFactorSetup } from 'mulguard'
274
670
 
275
671
  <TwoFactorSetup
276
672
  auth={auth}
@@ -280,53 +676,286 @@ import { TwoFactorSetup } from 'mukey'
280
676
  />
281
677
  ```
282
678
 
679
+ ### PassKey Components
680
+
681
+ ```typescript
682
+ import { PassKeyButton, PassKeyRegister } from 'mulguard'
683
+
684
+ // Register PassKey
685
+ <PassKeyRegister auth={auth} />
686
+
687
+ // Authenticate with PassKey
688
+ <PassKeyButton auth={auth} />
689
+ ```
690
+
691
+ ---
692
+
693
+ ## ๐Ÿ”’ Security
694
+
695
+ Mulguard implements **comprehensive security features** with automatic input validation and sanitization:
696
+
697
+ ### โœ… Built-in Security Features
698
+
699
+ #### Input Validation & Sanitization
700
+ - **Automatic email validation** - Validates and sanitizes email addresses
701
+ - **Password length checks** - Prevents DoS attacks with extremely long passwords
702
+ - **Provider validation** - Sanitizes OAuth provider strings to prevent injection
703
+ - **OTP code validation** - Validates OTP code format before processing
704
+ - **XSS Prevention** - Automatic HTML escaping and input sanitization
705
+
706
+ #### CSRF Protection
707
+ - Token-based CSRF protection for OAuth flows
708
+ - State parameter validation with constant-time comparison
709
+ - Secure state storage (pluggable for production - Redis, Database, etc.)
710
+
711
+ #### Error Handling
712
+ - **Generic error messages** - Prevents information disclosure
713
+ - **Error codes** - Programmatic error handling without exposing details
714
+ - **Security logging** - Logs authentication events (with sensitive data masked)
715
+
716
+ #### Secure Cookies
717
+ - HttpOnly cookies (prevents JavaScript access)
718
+ - Secure flag in production (HTTPS only)
719
+ - SameSite attribute (CSRF protection)
720
+ - Configurable expiration
721
+
722
+ #### Rate Limiting
723
+ - Configurable rate limiting
724
+ - Client-side tracking
725
+ - Automatic throttling
726
+ - Circuit breaker pattern for token refresh
727
+
728
+ ### Security Best Practices
729
+
730
+ ```typescript
731
+ // โœ… Good: Generic error messages
732
+ return {
733
+ success: false,
734
+ error: 'Invalid credentials',
735
+ errorCode: 'INVALID_CREDENTIALS'
736
+ }
737
+
738
+ // โŒ Bad: Information disclosure
739
+ return {
740
+ success: false,
741
+ error: 'User not found with email: user@example.com'
742
+ }
743
+ ```
744
+
745
+ ### Security Logging
746
+
747
+ All authentication events are automatically logged with sensitive data masked:
748
+
749
+ ```typescript
750
+ // Logs show: "Sign in successful" with email: "use***"
751
+ // Never logs full email addresses or passwords
752
+ ```
753
+
754
+ For detailed security documentation, see the [Security Guide](./docs/SECURITY.md) and [Complete Guide](./GUIDE.md).
755
+
756
+ ---
757
+
283
758
  ## ๐Ÿ”Œ Backend Integration
284
759
 
285
- Mukey expects your backend to provide the following endpoints:
760
+ Mulguard is designed to work with your existing backend. You implement the authentication logic through **actions**, which can:
286
761
 
287
- ### Authentication Endpoints
762
+ - Connect to your database
763
+ - Call your API endpoints
764
+ - Use your existing authentication services
765
+ - Integrate with third-party services
288
766
 
289
- - `POST /api/auth/sign-in` - Sign in with email/password
290
- - `POST /api/auth/sign-up` - Register new user
291
- - `POST /api/auth/sign-out` - Sign out
292
- - `GET /api/auth/session` - Get current session
293
- - `POST /api/auth/reset-password` - Request password reset
294
- - `POST /api/auth/verify-email` - Verify email address
767
+ ### Example: Database Integration
295
768
 
296
- ### OAuth Endpoints
769
+ ```typescript
770
+ import { mulguard } from 'mulguard'
771
+ import { db } from '@/lib/db'
772
+ import { comparePassword, hashPassword } from '@/lib/password'
773
+
774
+ export const auth = mulguard({
775
+ actions: {
776
+ signIn: {
777
+ email: async ({ email, password }) => {
778
+ const user = await db.user.findUnique({ where: { email } })
779
+
780
+ if (!user || !await comparePassword(password, user.password)) {
781
+ return { success: false, error: 'Invalid credentials' }
782
+ }
783
+
784
+ return {
785
+ success: true,
786
+ user: {
787
+ id: user.id,
788
+ email: user.email,
789
+ name: user.name,
790
+ },
791
+ session: {
792
+ user: { /* ... */ },
793
+ expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
794
+ },
795
+ }
796
+ },
797
+ },
798
+ // ... more actions
799
+ },
800
+ })
801
+ ```
297
802
 
298
- - `GET /api/auth/oauth/:provider` - Initiate OAuth flow
299
- - `POST /api/auth/oauth/:provider/callback` - Handle OAuth callback
803
+ ### Example: API Integration
300
804
 
301
- ### 2FA Endpoints
805
+ ```typescript
806
+ import { mulguard } from 'mulguard'
807
+
808
+ export const auth = mulguard({
809
+ actions: {
810
+ signIn: {
811
+ email: async ({ email, password }) => {
812
+ const response = await fetch('https://api.example.com/auth/signin', {
813
+ method: 'POST',
814
+ headers: { 'Content-Type': 'application/json' },
815
+ body: JSON.stringify({ email, password }),
816
+ })
817
+
818
+ if (!response.ok) {
819
+ return { success: false, error: 'Authentication failed' }
820
+ }
821
+
822
+ const data = await response.json()
823
+ return {
824
+ success: true,
825
+ user: data.user,
826
+ session: data.session,
827
+ }
828
+ },
829
+ },
830
+ },
831
+ })
832
+ ```
302
833
 
303
- - `POST /api/auth/2fa/enable` - Enable 2FA
304
- - `POST /api/auth/2fa/verify` - Verify 2FA code
305
- - `POST /api/auth/2fa/disable` - Disable 2FA
306
- - `POST /api/auth/2fa/regenerate` - Generate backup codes
307
- - `GET /api/auth/2fa/status` - Check 2FA status
834
+ ---
308
835
 
309
- ### PassKey Endpoints
836
+ ## ๐Ÿš€ Advanced Features
310
837
 
311
- - `POST /api/auth/passkey/register` - Register PassKey
312
- - `POST /api/auth/passkey/authenticate` - Authenticate with PassKey
313
- - `GET /api/auth/passkey/list` - List registered PassKeys
314
- - `DELETE /api/auth/passkey/:id` - Remove PassKey
838
+ ### Token Refresh
315
839
 
316
- See [Backend Integration Guide](./docs/BACKEND_INTEGRATION.md) for detailed API specifications.
840
+ Automatic token refresh is built-in when you provide a `refreshSession` action:
317
841
 
318
- ## ๐Ÿ”’ Security
842
+ ```typescript
843
+ actions: {
844
+ refreshSession: async () => {
845
+ // Your token refresh logic
846
+ const newSession = await yourApi.refreshToken()
847
+ return newSession
848
+ },
849
+ }
850
+ ```
319
851
 
320
- Mukey implements multiple security features:
852
+ ### Custom Callbacks
321
853
 
322
- - **CSRF Protection** - Token-based CSRF protection
323
- - **XSS Prevention** - Input sanitization and HTML escaping
324
- - **Rate Limiting** - Client-side rate limit tracking
325
- - **Security Headers** - Automatic security headers
326
- - **Input Validation** - Comprehensive input validation
327
- - **Secure Cookies** - HttpOnly, Secure, SameSite cookies
854
+ ```typescript
855
+ callbacks: {
856
+ onSignIn: async (user, session) => {
857
+ // Track sign-in analytics
858
+ await analytics.track('user_signed_in', { userId: user.id })
859
+ },
860
+ onSignOut: async (user) => {
861
+ // Cleanup logic
862
+ await cleanupUserSession(user.id)
863
+ },
864
+ onError: async (error, context) => {
865
+ // Error logging
866
+ console.error(`Auth error in ${context}:`, error)
867
+ },
868
+ }
869
+ ```
870
+
871
+ ### OAuth State Store
872
+
873
+ For production, use a persistent OAuth state store:
874
+
875
+ ```typescript
876
+ import { createRedisOAuthStateStore } from 'mulguard'
877
+
878
+ const auth = mulguard({
879
+ oauthStateStore: createRedisOAuthStateStore(redisClient),
880
+ // ... rest of config
881
+ })
882
+ ```
883
+
884
+ ---
885
+
886
+ ## ๐Ÿ“š API Reference
887
+
888
+ ### Core Functions
889
+
890
+ #### `mulguard(config: MulguardConfig): MulguardInstance`
891
+
892
+ Creates a new Mulguard authentication instance.
893
+
894
+ #### `getServerSession(auth: MulguardInstance): Promise<Session | null>`
895
+
896
+ Gets the current session on the server.
897
+
898
+ ### Client Hooks
899
+
900
+ #### `useAuth(auth: MulguardInstance)`
901
+
902
+ Returns authentication methods and state.
903
+
904
+ ```typescript
905
+ const { signIn, signOut, isLoading } = useAuth(auth)
906
+ ```
907
+
908
+ #### `useSession(auth: MulguardInstance)`
909
+
910
+ Returns the current session.
911
+
912
+ ```typescript
913
+ const { session, isLoading } = useSession(auth)
914
+ ```
915
+
916
+ ### Instance Methods
917
+
918
+ #### `auth.getSession(): Promise<Session | null>`
919
+
920
+ Gets the current session.
921
+
922
+ #### `auth.signIn.email(credentials): Promise<AuthResult>`
923
+
924
+ Signs in with email and password.
925
+
926
+ #### `auth.signIn.oauth(provider): Promise<{ url: string; state: string }>`
927
+
928
+ Initiates OAuth flow.
328
929
 
329
- See [Security Guide](./docs/SECURITY.md) for more details.
930
+ #### `auth.signOut(): Promise<{ success: boolean }>`
931
+
932
+ Signs out the current user.
933
+
934
+ For complete API documentation, see the [API Reference](./docs/API_REFERENCE.md).
935
+
936
+ ---
937
+
938
+ ## ๐Ÿ“– Examples & Guides
939
+
940
+ ### Complete Guide
941
+
942
+ ๐Ÿ“š **[Complete Usage Guide](./GUIDE.md)** - Comprehensive guide with:
943
+ - Best practices for writing `auth.ts`
944
+ - Production-ready examples
945
+ - Security recommendations
946
+ - Backend integration patterns
947
+ - Advanced usage examples
948
+
949
+ ### Code Examples
950
+
951
+ - **[Basic Email Authentication](./src/examples/email-auth.ts)** - Simple email/password setup
952
+ - **[OAuth Authentication](./src/examples/oauth-auth.ts)** - Google, GitHub, etc.
953
+ - **[PassKey Authentication](./src/examples/passkey-auth.ts)** - WebAuthn/PassKey setup
954
+ - **[Two-Factor Authentication](./src/examples/two-factor-auth.ts)** - 2FA/TOTP implementation
955
+ - **[Middleware Integration](./src/examples/middleware-example.ts)** - Next.js middleware
956
+ - **[Server Components](./src/examples/server-component-example.tsx)** - Server-side usage
957
+
958
+ ---
330
959
 
331
960
  ## ๐Ÿงช Testing
332
961
 
@@ -339,30 +968,77 @@ npm run test:watch
339
968
 
340
969
  # Coverage
341
970
  npm run test:coverage
971
+
972
+ # Type checking
973
+ npm run type-check
342
974
  ```
343
975
 
344
- ## ๐Ÿš€ CI/CD
976
+ ---
977
+
978
+ ## ๐Ÿค Contributing
979
+
980
+ Contributions are welcome! Please read our contributing guidelines before submitting a pull request.
981
+
982
+ 1. Fork the repository
983
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
984
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
985
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
986
+ 5. Open a Pull Request
987
+
988
+ ### Development Setup
345
989
 
346
- This project uses GitHub Actions with npm Trusted Publisher for secure publishing.
990
+ ```bash
991
+ # Clone the repository
992
+ git clone https://github.com/mulverse/mulguard.git
993
+
994
+ # Install dependencies
995
+ npm install
347
996
 
348
- - **CI**: Runs on every push/PR (lint, test, build)
349
- - **Publishing**: Automatic publishing via Changesets or manual release
350
- - **Security**: Uses OIDC (OpenID Connect) for authentication
997
+ # Run development build
998
+ npm run dev
351
999
 
352
- See [README_CI.md](./README_CI.md) for setup instructions.
1000
+ # Run tests
1001
+ npm test
1002
+ ```
1003
+
1004
+ ---
353
1005
 
354
1006
  ## ๐Ÿ“ License
355
1007
 
356
- MUV License - See [LICENSE](./LICENSE) file for details.
1008
+ This project is licensed under the **MUV (Mulverse M.U.V General Public License)**.
357
1009
 
358
- ## ๐Ÿค Contributing
1010
+ Copyright (C) 2022 Mulverse Inc.
1011
+
1012
+ See the [LICENSE](./LICENSE) file for details.
1013
+
1014
+ ---
1015
+
1016
+ ## ๐Ÿ’ฌ Support
1017
+
1018
+ - **๐Ÿ“– Complete Guide**: [GUIDE.md](./GUIDE.md) - Comprehensive usage guide with best practices
1019
+ - **๐Ÿ“š Documentation**: Check the [docs](./docs) directory for detailed guides
1020
+ - **๐Ÿ› Issues**: [GitHub Issues](https://github.com/mulverse/mulguard/issues)
1021
+ - **๐Ÿ’ฌ Discussions**: [GitHub Discussions](https://github.com/mulverse/mulguard/discussions)
1022
+
1023
+ ## ๐ŸŽฏ Key Features & Improvements
1024
+
1025
+ ### โœจ Latest Updates
1026
+
1027
+ - **โœ… Unified Sign-In Interface** - Use `auth.signIn('credentials', {...})` or `auth.signIn.email({...})`
1028
+ - **โœ… Automatic Input Validation** - Built-in email, password, and provider validation
1029
+ - **โœ… Enhanced Security** - Generic error messages, security logging, XSS/Injection prevention
1030
+ - **โœ… Single Unified Logic** - All sign-in methods use the same core logic
1031
+ - **โœ… Type-Safe** - Full TypeScript support with proper typing
1032
+ - **โœ… Production Ready** - Best practices built-in by default
1033
+
1034
+ ---
359
1035
 
360
- Contributions are welcome! Please read our contributing guidelines first.
1036
+ ## ๐ŸŒŸ About Mulverse
361
1037
 
362
- ## ๐Ÿ“ง Support
1038
+ **Mulguard** is part of the **Mulverse** ecosystem - a collection of modern, developer-friendly libraries and tools for building next-generation web applications.
363
1039
 
364
- For questions and support, please open an issue on GitHub.
1040
+ Visit [mulverse.com](https://mulverse.com) to learn more about our other projects.
365
1041
 
366
1042
  ---
367
1043
 
368
- Made with โค๏ธ by the Mukey Team
1044
+ **Made with โค๏ธ by the Mulverse Team**