@liedsonc/core-auth-kit 0.1.0

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 ADDED
@@ -0,0 +1,759 @@
1
+ # @liedsonc/core-auth-kit
2
+
3
+ Production-ready authentication UI package for Next.js App Router. Built with TypeScript, React Server Components, and shadcn/ui. Provides ready-to-use authentication pages and components that integrate with any backend via a simple `AuthClient` interface.
4
+
5
+ ## Features
6
+
7
+ - 🔐 **Complete Auth Flows** - Login, Register, Forgot Password, Reset Password, Email Verification
8
+ - 🎨 **Beautiful UI** - Built with shadcn/ui components, fully themeable and accessible
9
+ - 🔌 **Backend Agnostic** - Works with any authentication backend via `AuthClient` interface
10
+ - 📱 **Mobile-First** - Responsive design that works on all devices
11
+ - ♿ **Accessible** - WCAG compliant with proper ARIA attributes and keyboard navigation
12
+ - 🎯 **Type-Safe** - Full TypeScript support with strict typing
13
+ - 🚀 **Zero Config** - Works out-of-the-box with sensible defaults
14
+ - 🎨 **Customizable** - Override components, styles, and behavior as needed
15
+ - 🌙 **Dark Mode** - Built-in dark mode support via Tailwind CSS
16
+ - ⚙️ **Environment Configurable** - OAuth providers and settings via environment variables
17
+ - 📧 **Email Integration** - Built-in Resend email service support for verification and password reset emails
18
+
19
+ ## Installation
20
+
21
+ Simply install the package - all UI dependencies will be installed automatically:
22
+
23
+ ```bash
24
+ npm install @liedsonc/core-auth-kit
25
+ ```
26
+
27
+ ### Peer Dependencies
28
+
29
+ The following peer dependencies are required but should already be installed in your Next.js project:
30
+
31
+ - `next` (^15.0.0) - Next.js framework
32
+ - `react` (^19.0.0) - React library
33
+ - `react-dom` (^19.0.0) - React DOM library
34
+
35
+ If you're not using Next.js or these aren't installed, install them:
36
+
37
+ ```bash
38
+ npm install next react react-dom
39
+ ```
40
+
41
+ **Note:** The following dependencies are automatically installed with the package:
42
+ - `@radix-ui/react-label` - For accessible form labels
43
+ - `@radix-ui/react-slot` - For component composition
44
+ - `class-variance-authority` - For component variants
45
+ - `clsx` - For conditional class names
46
+ - `tailwind-merge` - For merging Tailwind classes
47
+
48
+ ### Email Service (Optional)
49
+
50
+ For email verification and password reset functionality, install Resend:
51
+
52
+ ```bash
53
+ npm install resend
54
+ ```
55
+
56
+ ### shadcn/ui Components
57
+
58
+ The package includes shadcn/ui components by default. Ensure your project has the shadcn/ui setup:
59
+
60
+ 1. Install shadcn/ui components (if not already installed):
61
+ ```bash
62
+ npx shadcn@latest add button input card label
63
+ ```
64
+
65
+ 2. Ensure your `tailwind.config.ts` includes the auth-ui styles:
66
+ ```ts
67
+ import type { Config } from "tailwindcss";
68
+
69
+ const config: Config = {
70
+ content: [
71
+ "./app/**/*.{js,ts,jsx,tsx,mdx}",
72
+ "./components/**/*.{js,ts,jsx,tsx,mdx}",
73
+ "./node_modules/@liedsonc/core-auth-kit/**/*.{js,ts,jsx,tsx}",
74
+ ],
75
+ // ... rest of config
76
+ };
77
+ ```
78
+
79
+ 3. Import the styles in your root layout:
80
+ ```tsx
81
+ import "@liedsonc/core-auth-kit/styles";
82
+ ```
83
+
84
+ ## Environment Variables
85
+
86
+ Create a `.env.local` file (or `.env`) with the following variables:
87
+
88
+ ```bash
89
+ NEXT_PUBLIC_APP_URL=http://localhost:3000
90
+
91
+ NEXT_PUBLIC_AUTH_REDIRECT_AFTER_LOGIN=/
92
+ NEXT_PUBLIC_AUTH_REDIRECT_AFTER_REGISTER=/login
93
+ NEXT_PUBLIC_AUTH_REDIRECT_AFTER_RESET=/login
94
+
95
+ NEXT_PUBLIC_OAUTH_GOOGLE_ENABLED=false
96
+ NEXT_PUBLIC_OAUTH_GOOGLE_CLIENT_ID=your_google_client_id
97
+ NEXT_PUBLIC_OAUTH_GOOGLE_REDIRECT_URI=http://localhost:3000/api/auth/google
98
+ OAUTH_GOOGLE_CLIENT_SECRET=your_google_client_secret
99
+
100
+ NEXT_PUBLIC_OAUTH_APPLE_ENABLED=false
101
+ NEXT_PUBLIC_OAUTH_APPLE_CLIENT_ID=your_apple_client_id
102
+ NEXT_PUBLIC_OAUTH_APPLE_REDIRECT_URI=http://localhost:3000/api/auth/apple
103
+ OAUTH_APPLE_CLIENT_SECRET=your_apple_client_secret
104
+
105
+ RESEND_API_KEY=re_your_resend_api_key
106
+ RESEND_FROM_EMAIL=noreply@yourdomain.com
107
+ RESEND_FROM_NAME=Your App Name
108
+ NEXT_PUBLIC_APP_NAME=Your App Name
109
+ ```
110
+
111
+ ### Environment Variable Reference
112
+
113
+ | Variable | Description | Required | Default |
114
+ |----------|-------------|----------|---------|
115
+ | `NEXT_PUBLIC_APP_URL` | Your application base URL | No | `http://localhost:3000` |
116
+ | `NEXT_PUBLIC_AUTH_REDIRECT_AFTER_LOGIN` | Redirect URL after successful login | No | `/` |
117
+ | `NEXT_PUBLIC_AUTH_REDIRECT_AFTER_REGISTER` | Redirect URL after registration | No | `/login` |
118
+ | `NEXT_PUBLIC_AUTH_REDIRECT_AFTER_RESET` | Redirect URL after password reset | No | `/login` |
119
+ | `NEXT_PUBLIC_OAUTH_GOOGLE_ENABLED` | Enable/disable Google OAuth | No | `false` |
120
+ | `NEXT_PUBLIC_OAUTH_GOOGLE_CLIENT_ID` | Google OAuth Client ID | Yes (if Google enabled) | - |
121
+ | `NEXT_PUBLIC_OAUTH_GOOGLE_REDIRECT_URI` | Google OAuth redirect URI | Yes (if Google enabled) | - |
122
+ | `OAUTH_GOOGLE_CLIENT_SECRET` | Google OAuth Client Secret (server-only) | Yes (if Google enabled) | - |
123
+ | `NEXT_PUBLIC_OAUTH_APPLE_ENABLED` | Enable/disable Apple OAuth | No | `false` |
124
+ | `NEXT_PUBLIC_OAUTH_APPLE_CLIENT_ID` | Apple OAuth Client ID | Yes (if Apple enabled) | - |
125
+ | `NEXT_PUBLIC_OAUTH_APPLE_REDIRECT_URI` | Apple OAuth redirect URI | Yes (if Apple enabled) | - |
126
+ | `OAUTH_APPLE_CLIENT_SECRET` | Apple OAuth Client Secret (server-only) | Yes (if Apple enabled) | - |
127
+ | `RESEND_API_KEY` | Resend API key for sending emails | Yes (if using email features) | - |
128
+ | `RESEND_FROM_EMAIL` | Email address to send from (must be verified in Resend) | Yes (if using email features) | - |
129
+ | `RESEND_FROM_NAME` | Display name for email sender | No | - |
130
+ | `NEXT_PUBLIC_APP_NAME` | Your application name (used in emails) | No | `App` |
131
+
132
+ **Note:** Variables prefixed with `NEXT_PUBLIC_` are exposed to the browser. Secrets should NOT use this prefix.
133
+
134
+ ## Quick Start
135
+
136
+ ### 1. Implement AuthClient
137
+
138
+ Create an `AuthClient` that connects to your backend:
139
+
140
+ ```typescript
141
+ import type { AuthClient } from "@liedsonc/core-auth-kit";
142
+
143
+ export const myAuthClient: AuthClient = {
144
+ async login(email, password) {
145
+ const response = await fetch("/api/auth/login", {
146
+ method: "POST",
147
+ headers: { "Content-Type": "application/json" },
148
+ body: JSON.stringify({ email, password }),
149
+ });
150
+
151
+ if (!response.ok) {
152
+ return {
153
+ success: false,
154
+ error: { code: "INVALID_CREDENTIALS", message: "Invalid email or password" },
155
+ };
156
+ }
157
+
158
+ return { success: true };
159
+ },
160
+
161
+ async register(email, password) {
162
+ const response = await fetch("/api/auth/register", {
163
+ method: "POST",
164
+ headers: { "Content-Type": "application/json" },
165
+ body: JSON.stringify({ email, password }),
166
+ });
167
+
168
+ if (!response.ok) {
169
+ const data = await response.json();
170
+ return {
171
+ success: false,
172
+ error: { code: data.code || "REGISTRATION_FAILED", message: data.message },
173
+ };
174
+ }
175
+
176
+ return { success: true };
177
+ },
178
+
179
+ async logout() {
180
+ await fetch("/api/auth/logout", { method: "POST" });
181
+ },
182
+
183
+ async forgotPassword(email) {
184
+ const response = await fetch("/api/auth/forgot-password", {
185
+ method: "POST",
186
+ headers: { "Content-Type": "application/json" },
187
+ body: JSON.stringify({ email }),
188
+ });
189
+
190
+ return response.ok ? { success: true } : {
191
+ success: false,
192
+ error: { code: "FAILED", message: "Failed to send reset email" },
193
+ };
194
+ },
195
+
196
+ async resetPassword(token, newPassword) {
197
+ const response = await fetch("/api/auth/reset-password", {
198
+ method: "POST",
199
+ headers: { "Content-Type": "application/json" },
200
+ body: JSON.stringify({ token, newPassword }),
201
+ });
202
+
203
+ if (!response.ok) {
204
+ return {
205
+ success: false,
206
+ error: { code: "INVALID_TOKEN", message: "Invalid or expired token" },
207
+ };
208
+ }
209
+
210
+ return { success: true };
211
+ },
212
+
213
+ async verifyEmail(token) {
214
+ const response = await fetch("/api/auth/verify-email", {
215
+ method: "POST",
216
+ headers: { "Content-Type": "application/json" },
217
+ body: JSON.stringify({ token }),
218
+ });
219
+
220
+ if (!response.ok) {
221
+ const data = await response.json();
222
+ return {
223
+ success: false,
224
+ error: { code: data.code || "INVALID", message: data.message },
225
+ };
226
+ }
227
+
228
+ return { success: true };
229
+ },
230
+
231
+ async getSession() {
232
+ const response = await fetch("/api/auth/session");
233
+ if (!response.ok) return null;
234
+ return response.json();
235
+ },
236
+ };
237
+ ```
238
+
239
+ ### 2. Setup Provider with Environment Variables
240
+
241
+ Create a utility to load OAuth config from environment variables:
242
+
243
+ ```typescript
244
+ // lib/oauth-config.ts
245
+ import type { OAuthProvider } from "@liedsonc/core-auth-kit";
246
+
247
+ export interface OAuthProviderConfig {
248
+ provider: OAuthProvider;
249
+ enabled: boolean;
250
+ clientId?: string;
251
+ redirectUri?: string;
252
+ }
253
+
254
+ export function getOAuthProvidersFromEnv(): OAuthProviderConfig[] {
255
+ const providers: OAuthProviderConfig[] = [];
256
+
257
+ if (process.env.NEXT_PUBLIC_OAUTH_GOOGLE_ENABLED === "true") {
258
+ providers.push({
259
+ provider: "google",
260
+ enabled: true,
261
+ clientId: process.env.NEXT_PUBLIC_OAUTH_GOOGLE_CLIENT_ID,
262
+ redirectUri: process.env.NEXT_PUBLIC_OAUTH_GOOGLE_REDIRECT_URI,
263
+ });
264
+ }
265
+
266
+ if (process.env.NEXT_PUBLIC_OAUTH_APPLE_ENABLED === "true") {
267
+ providers.push({
268
+ provider: "apple",
269
+ enabled: true,
270
+ clientId: process.env.NEXT_PUBLIC_OAUTH_APPLE_CLIENT_ID,
271
+ redirectUri: process.env.NEXT_PUBLIC_OAUTH_APPLE_REDIRECT_URI,
272
+ });
273
+ }
274
+
275
+ return providers;
276
+ }
277
+ ```
278
+
279
+ Wrap your auth routes with `AuthUIProvider`:
280
+
281
+ ```tsx
282
+ // app/(auth)/layout.tsx
283
+ "use client";
284
+
285
+ import { AuthUIProvider } from "@liedsonc/core-auth-kit";
286
+ import { myAuthClient } from "@/lib/auth-client";
287
+ import { getOAuthProvidersFromEnv } from "@/lib/oauth-config";
288
+
289
+ export default function AuthLayout({ children }: { children: React.ReactNode }) {
290
+ return (
291
+ <AuthUIProvider
292
+ config={{
293
+ authClient: myAuthClient,
294
+ oauthProviders: getOAuthProvidersFromEnv(),
295
+ redirectAfterLogin: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_LOGIN || "/",
296
+ redirectAfterRegister: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_REGISTER || "/login",
297
+ redirectAfterReset: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_RESET || "/login",
298
+ }}
299
+ >
300
+ {children}
301
+ </AuthUIProvider>
302
+ );
303
+ }
304
+ ```
305
+
306
+ ### 3. Create Auth Pages
307
+
308
+ Use the pre-built page components:
309
+
310
+ ```tsx
311
+ // app/(auth)/login/page.tsx
312
+ import { LoginPage } from "@liedsonc/core-auth-kit";
313
+
314
+ export default function Login() {
315
+ return <LoginPage />;
316
+ }
317
+ ```
318
+
319
+ ```tsx
320
+ // app/(auth)/register/page.tsx
321
+ import { RegisterPage } from "@liedsonc/core-auth-kit";
322
+
323
+ export default function Register() {
324
+ return <RegisterPage />;
325
+ }
326
+ ```
327
+
328
+ ```tsx
329
+ // app/(auth)/forgot-password/page.tsx
330
+ import { ForgotPasswordPage } from "@liedsonc/core-auth-kit";
331
+
332
+ export default function ForgotPassword() {
333
+ return <ForgotPasswordPage />;
334
+ }
335
+ ```
336
+
337
+ ```tsx
338
+ // app/(auth)/reset-password/page.tsx
339
+ import { ResetPasswordPage } from "@liedsonc/core-auth-kit";
340
+
341
+ export default function ResetPassword() {
342
+ return <ResetPasswordPage />;
343
+ }
344
+ ```
345
+
346
+ ```tsx
347
+ // app/(auth)/verify-email/page.tsx
348
+ import { VerifyEmailPage } from "@liedsonc/core-auth-kit";
349
+
350
+ export default function VerifyEmail() {
351
+ return <VerifyEmailPage />;
352
+ }
353
+ ```
354
+
355
+ ## Email Integration with Resend
356
+
357
+ The package includes utilities for sending verification and password reset emails via Resend. Here's how to integrate it:
358
+
359
+ ### 1. Setup Resend
360
+
361
+ 1. Sign up for a [Resend account](https://resend.com)
362
+ 2. Get your API key from the dashboard
363
+ 3. Verify your domain (or use Resend's test domain for development)
364
+ 4. Add your credentials to `.env.local`:
365
+
366
+ ```bash
367
+ RESEND_API_KEY=re_your_api_key_here
368
+ RESEND_FROM_EMAIL=noreply@yourdomain.com
369
+ RESEND_FROM_NAME=Your App Name
370
+ NEXT_PUBLIC_APP_NAME=Your App Name
371
+ ```
372
+
373
+ ### 2. Use Resend Email Service
374
+
375
+ Import and use the Resend email service in your AuthClient implementation:
376
+
377
+ ```typescript
378
+ // lib/auth-client.ts
379
+ import type { AuthClient } from "@liedsonc/core-auth-kit";
380
+ import { createResendEmailService } from "@/lib/resend-email";
381
+ import { randomBytes } from "crypto";
382
+
383
+ const emailService = createResendEmailService({
384
+ apiKey: process.env.RESEND_API_KEY!,
385
+ from: process.env.RESEND_FROM_EMAIL!,
386
+ fromName: process.env.RESEND_FROM_NAME,
387
+ appName: process.env.NEXT_PUBLIC_APP_NAME || "App",
388
+ });
389
+
390
+ const appUrl = process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000";
391
+
392
+ export const myAuthClient: AuthClient = {
393
+ async register(email, password) {
394
+ // Your registration logic here
395
+ // ... save user to database
396
+
397
+ // Generate verification token
398
+ const token = randomBytes(32).toString("hex");
399
+ // Store token in database with expiration
400
+ // await db.verificationTokens.create({ email, token, expiresAt: ... });
401
+
402
+ // Send verification email
403
+ const verificationUrl = `${appUrl}/verify-email?token=${token}`;
404
+ const emailResult = await emailService.sendVerificationEmail({
405
+ email,
406
+ token,
407
+ verificationUrl,
408
+ });
409
+
410
+ if (!emailResult.success) {
411
+ return {
412
+ success: false,
413
+ error: { code: "EMAIL_SEND_FAILED", message: "Failed to send verification email" },
414
+ };
415
+ }
416
+
417
+ return { success: true };
418
+ },
419
+
420
+ async forgotPassword(email) {
421
+ // Generate reset token
422
+ const token = randomBytes(32).toString("hex");
423
+ // Store token in database with expiration (e.g., 1 hour)
424
+ // await db.resetTokens.create({ email, token, expiresAt: ... });
425
+
426
+ // Send password reset email
427
+ const resetUrl = `${appUrl}/reset-password?token=${token}`;
428
+ const emailResult = await emailService.sendPasswordResetEmail({
429
+ email,
430
+ token,
431
+ resetUrl,
432
+ expiresIn: "1 hour",
433
+ });
434
+
435
+ if (!emailResult.success) {
436
+ return {
437
+ success: false,
438
+ error: { code: "EMAIL_SEND_FAILED", message: "Failed to send reset email" },
439
+ };
440
+ }
441
+
442
+ return { success: true };
443
+ },
444
+
445
+ // ... other AuthClient methods
446
+ };
447
+ ```
448
+
449
+ ### 3. Example Implementation
450
+
451
+ See `lib/auth-client-with-resend.ts` for a complete example implementation that includes:
452
+ - Token generation and validation
453
+ - Email sending with Resend
454
+ - Token expiration handling
455
+ - Error handling
456
+
457
+ ### 4. Customizing Email Templates
458
+
459
+ The email templates are built into the `ResendEmailService` class. To customize them:
460
+
461
+ 1. Extend the `ResendEmailService` class
462
+ 2. Override the template methods (`getVerificationEmailTemplate`, `getPasswordResetEmailTemplate`)
463
+ 3. Use your custom service instance
464
+
465
+ ```typescript
466
+ class CustomEmailService extends ResendEmailService {
467
+ private getVerificationEmailTemplate({ verificationUrl, appName }: { verificationUrl: string; appName: string }): string {
468
+ // Your custom HTML template
469
+ return `...`;
470
+ }
471
+ }
472
+ ```
473
+
474
+ ### 5. Email Service API
475
+
476
+ ```typescript
477
+ import { createResendEmailService, ResendEmailService } from "@/lib/resend-email";
478
+
479
+ // Create service instance
480
+ const emailService = createResendEmailService({
481
+ apiKey: process.env.RESEND_API_KEY!,
482
+ from: process.env.RESEND_FROM_EMAIL!,
483
+ fromName: "Your App",
484
+ appName: "Your App Name",
485
+ });
486
+
487
+ // Send verification email
488
+ await emailService.sendVerificationEmail({
489
+ email: "user@example.com",
490
+ token: "verification_token",
491
+ verificationUrl: "https://yourapp.com/verify-email?token=...",
492
+ appName: "Your App", // Optional, uses service default if not provided
493
+ });
494
+
495
+ // Send password reset email
496
+ await emailService.sendPasswordResetEmail({
497
+ email: "user@example.com",
498
+ token: "reset_token",
499
+ resetUrl: "https://yourapp.com/reset-password?token=...",
500
+ appName: "Your App", // Optional
501
+ expiresIn: "1 hour", // Optional, default is "1 hour"
502
+ });
503
+ ```
504
+
505
+ ## API Reference
506
+
507
+ ### Components
508
+
509
+ #### Pages
510
+
511
+ - **`LoginPage`** - Complete login page with email/password and OAuth
512
+ - **`RegisterPage`** - Registration page with password strength indicator
513
+ - **`ForgotPasswordPage`** - Password reset request page
514
+ - **`ResetPasswordPage`** - Password reset form (requires token query param)
515
+ - **`VerifyEmailPage`** - Email verification page (requires token query param)
516
+
517
+ #### UI Components
518
+
519
+ - **`AuthCard`** - Reusable card layout for auth pages
520
+ - **`AuthForm`** - Form wrapper with loading/error states
521
+ - **`FormField`** - Form field with label and error display
522
+ - **`PasswordInput`** - Password input with show/hide toggle and strength indicator
523
+ - **`OAuthButtons`** - OAuth provider buttons (Google, Apple)
524
+ - **`ErrorMessage`** - Error message display component
525
+ - **`SuccessMessage`** - Success message display component
526
+ - **`LoadingSpinner`** - Loading spinner component
527
+
528
+ ### Hooks
529
+
530
+ #### `useAuth()`
531
+
532
+ Main authentication hook that provides all auth methods:
533
+
534
+ ```typescript
535
+ const {
536
+ login, // (email: string, password: string) => Promise<AuthResult>
537
+ register, // (email: string, password: string) => Promise<AuthResult>
538
+ logout, // () => Promise<void>
539
+ forgotPassword, // (email: string) => Promise<AuthResult>
540
+ resetPassword, // (token: string, newPassword: string) => Promise<AuthResult>
541
+ verifyEmail, // (token: string) => Promise<AuthResult>
542
+ session, // AuthSession | null
543
+ loadSession, // () => Promise<AuthSession | null>
544
+ loading, // boolean
545
+ error, // AuthError | null
546
+ clearError, // () => void
547
+ } = useAuth();
548
+ ```
549
+
550
+ #### `useOAuth(onRedirect)`
551
+
552
+ OAuth authentication hook:
553
+
554
+ ```typescript
555
+ const { signIn, loadingProvider } = useOAuth(
556
+ (provider) => `/api/auth/${provider}`
557
+ );
558
+ ```
559
+
560
+ ### Types
561
+
562
+ ```typescript
563
+ interface AuthClient {
564
+ login: (email: string, password: string) => Promise<AuthResult>;
565
+ register: (email: string, password: string) => Promise<AuthResult>;
566
+ logout: () => Promise<void>;
567
+ forgotPassword: (email: string) => Promise<AuthResult>;
568
+ resetPassword: (token: string, newPassword: string) => Promise<AuthResult>;
569
+ verifyEmail: (token: string) => Promise<AuthResult>;
570
+ getSession?: () => Promise<AuthSession | null>;
571
+ }
572
+
573
+ interface AuthUIConfig {
574
+ authClient: AuthClient;
575
+ oauthProviders?: { provider: OAuthProvider; enabled: boolean }[];
576
+ logo?: ReactNode;
577
+ redirectAfterLogin?: string;
578
+ redirectAfterRegister?: string;
579
+ redirectAfterReset?: string;
580
+ }
581
+
582
+ type AuthResult =
583
+ | { success: true }
584
+ | { success: false; error: AuthError };
585
+
586
+ interface AuthError {
587
+ code: string;
588
+ message: string;
589
+ }
590
+
591
+ type OAuthProvider = "google" | "apple";
592
+ ```
593
+
594
+ ## Customization
595
+
596
+ ### Custom Logo
597
+
598
+ ```tsx
599
+ <AuthUIProvider
600
+ config={{
601
+ authClient: myAuthClient,
602
+ logo: <img src="/logo.svg" alt="Logo" />,
603
+ }}
604
+ >
605
+ {children}
606
+ </AuthUIProvider>
607
+ ```
608
+
609
+ ### OAuth Configuration via Environment Variables
610
+
611
+ Enable/disable OAuth providers and configure credentials via environment variables:
612
+
613
+ ```bash
614
+ NEXT_PUBLIC_OAUTH_GOOGLE_ENABLED=true
615
+ NEXT_PUBLIC_OAUTH_GOOGLE_CLIENT_ID=your_client_id
616
+ NEXT_PUBLIC_OAUTH_GOOGLE_REDIRECT_URI=https://yourapp.com/api/auth/google
617
+ OAUTH_GOOGLE_CLIENT_SECRET=your_client_secret
618
+ ```
619
+
620
+ The `getOAuthProvidersFromEnv()` utility automatically reads these and configures providers.
621
+
622
+ ### Custom Redirects
623
+
624
+ Set redirects via environment variables or config:
625
+
626
+ ```tsx
627
+ <AuthUIProvider
628
+ config={{
629
+ authClient: myAuthClient,
630
+ redirectAfterLogin: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_LOGIN || "/dashboard",
631
+ redirectAfterRegister: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_REGISTER || "/onboarding",
632
+ redirectAfterReset: process.env.NEXT_PUBLIC_AUTH_REDIRECT_AFTER_RESET || "/login?reset=success",
633
+ }}
634
+ >
635
+ {children}
636
+ </AuthUIProvider>
637
+ ```
638
+
639
+ ### Using Individual Components
640
+
641
+ You can also use components individually to build custom pages:
642
+
643
+ ```tsx
644
+ import { AuthCard, AuthForm, FormField, PasswordInput, Button } from "@liedsonc/core-auth-kit";
645
+
646
+ export function CustomLoginPage() {
647
+ return (
648
+ <AuthCard title="Sign In">
649
+ <AuthForm onSubmit={handleSubmit}>
650
+ <FormField label="Email" htmlFor="email">
651
+ <Input id="email" type="email" />
652
+ </FormField>
653
+ <FormField label="Password" htmlFor="password">
654
+ <PasswordInput id="password" />
655
+ </FormField>
656
+ <Button type="submit">Sign In</Button>
657
+ </AuthForm>
658
+ </AuthCard>
659
+ );
660
+ }
661
+ ```
662
+
663
+ ## Production Setup
664
+
665
+ ### 1. Environment Variables
666
+
667
+ Copy `.env.example` to `.env.local` and fill in your production values:
668
+
669
+ ```bash
670
+ cp .env.example .env.local
671
+ ```
672
+
673
+ **Important:** Never commit `.env.local` to version control. Add it to `.gitignore`.
674
+
675
+ ### 2. OAuth Provider Setup
676
+
677
+ #### Google OAuth
678
+
679
+ 1. Go to [Google Cloud Console](https://console.cloud.google.com/)
680
+ 2. Create a new project or select existing
681
+ 3. Enable Google+ API
682
+ 4. Create OAuth 2.0 credentials
683
+ 5. Add authorized redirect URIs
684
+ 6. Copy Client ID and Client Secret to `.env.local`
685
+
686
+ #### Apple OAuth
687
+
688
+ 1. Go to [Apple Developer Portal](https://developer.apple.com/)
689
+ 2. Create an App ID
690
+ 3. Create a Services ID
691
+ 4. Configure Sign in with Apple
692
+ 5. Add redirect URIs
693
+ 6. Copy Client ID and Client Secret to `.env.local`
694
+
695
+ ### 3. Build and Deploy
696
+
697
+ ```bash
698
+ npm run build
699
+ npm start
700
+ ```
701
+
702
+ ## Styling
703
+
704
+ The package uses Tailwind CSS and follows shadcn/ui conventions. Customize colors via CSS variables:
705
+
706
+ ```css
707
+ :root {
708
+ --primary: 222.2 47.4% 11.2%;
709
+ --primary-foreground: 210 40% 98%;
710
+ /* ... other variables */
711
+ }
712
+ ```
713
+
714
+ See [shadcn/ui theming](https://ui.shadcn.com/docs/theming) for details.
715
+
716
+ ## Security Considerations
717
+
718
+ - **No User Enumeration**: Error messages don't reveal if an email exists
719
+ - **Secure Defaults**: Password inputs prevent autofill leaks
720
+ - **CSRF Protection**: Implement CSRF tokens in your `AuthClient`
721
+ - **Rate Limiting**: Implement rate limiting in your backend
722
+ - **Token Security**: Handle tokens securely in your `AuthClient`
723
+ - **Environment Variables**: Never expose secrets in client-side code (use `NEXT_PUBLIC_` prefix only for public values)
724
+
725
+ ## Browser Support
726
+
727
+ - Chrome (latest)
728
+ - Firefox (latest)
729
+ - Safari (latest)
730
+ - Edge (latest)
731
+
732
+ ## Project Structure
733
+
734
+ ```
735
+ core-auth-kit/
736
+ ├── auth-ui/ # Package source code
737
+ │ ├── components/ # UI components
738
+ │ ├── hooks/ # React hooks
739
+ │ ├── pages/ # Page components
740
+ │ ├── types/ # TypeScript types
741
+ │ ├── styles/ # CSS styles
742
+ │ └── index.ts # Main export
743
+ ├── app/ # Example Next.js app
744
+ ├── lib/ # Utilities (oauth-config, auth-client)
745
+ ├── .env.example # Environment variables template
746
+ └── README.md # This file
747
+ ```
748
+
749
+ ## Contributing
750
+
751
+ Contributions are welcome! Please read our contributing guidelines first.
752
+
753
+ ## License
754
+
755
+ MIT
756
+
757
+ ## Support
758
+
759
+ For issues, questions, or contributions, please open an issue on GitHub.