@webdevarif/auth
v1.0.7
Published
A comprehensive authentication package for Next.js applications with customizable forms, pages, and middleware
Maintainers
Readme
@webdevarif/auth
A comprehensive authentication package for Next.js applications with customizable forms, pages, and middleware. Built on top of NextAuth.js v4 with Prisma integration.
Features
- 🔐 Complete Authentication System - Login, register, email verification
- 🎨 Customizable UI Components - Pre-built forms and pages with Tailwind CSS
- 🛡️ Middleware Support - Route protection and authentication guards
- 🔧 Flexible Configuration - Environment-based setup with custom callbacks
- 📱 Responsive Design - Mobile-first approach with modern UI
- 🌐 Internationalization Ready - Built-in i18n support
- 🎯 TypeScript First - Full type safety and IntelliSense support
- 🔌 Plugin Architecture - Easy to extend and customize
Installation
npm install @webdevarif/auth
# or
pnpm add @webdevarif/auth
# or
yarn add @webdevarif/authPeer Dependencies
Make sure you have these packages installed:
npm install next@>=14.0.0 react@>=18.0.0 react-dom@>=18.0.0 next-auth@>=4.24.0 @auth/prisma-adapter@>=1.0.0 prisma@>=5.0.0Quick Start
1. Environment Variables
Create a .env.local file:
# Database
DATABASE_URL="your-database-url"
# NextAuth
NEXTAUTH_SECRET="your-secret-key"
NEXTAUTH_URL="http://localhost:3000"
# OAuth Providers (optional)
AUTH_GOOGLE_ID="your-google-client-id"
AUTH_GOOGLE_SECRET="your-google-client-secret"
# Email Configuration (optional)
EMAIL_FROM="[email protected]"
EMAIL_SERVER_HOST="smtp.gmail.com"
EMAIL_SERVER_PORT=587
EMAIL_SERVER_USER="[email protected]"
EMAIL_SERVER_PASSWORD="your-app-password"2. Prisma Schema
Add the required models to your schema.prisma:
model User {
id Int @id @default(autoincrement())
name String?
username String @unique
email String @unique
emailVerified DateTime?
image String?
password String?
phone String?
role String @default("USER")
plan String @default("FREE")
website_url String?
is_active Boolean @default(true)
is_superuser Boolean @default(false)
created_at DateTime @default(now())
updated_at DateTime @updatedAt
accounts Account[]
sessions Session[]
}
model Account {
id String @id @default(cuid())
userId Int
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
}
model Session {
id String @id @default(cuid())
sessionToken String @unique
userId Int
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@map("sessions")
}
model VerificationToken {
identifier String
token String @unique
expires DateTime
@@unique([identifier, token])
}3. Setup Authentication
Create lib/auth.ts:
import { createAuth, AuthConfig } from '@webdevarif/auth';
const authConfig: AuthConfig = {
databaseUrl: process.env.DATABASE_URL!,
nextAuthSecret: process.env.NEXTAUTH_SECRET!,
nextAuthUrl: process.env.NEXTAUTH_URL!,
// Optional: Google OAuth
google: {
clientId: process.env.AUTH_GOOGLE_ID!,
clientSecret: process.env.AUTH_GOOGLE_SECRET!,
},
// Optional: Email configuration
email: {
from: process.env.EMAIL_FROM!,
server: {
host: process.env.EMAIL_SERVER_HOST!,
port: parseInt(process.env.EMAIL_SERVER_PORT!),
auth: {
user: process.env.EMAIL_SERVER_USER!,
pass: process.env.EMAIL_SERVER_PASSWORD!,
},
},
},
// Optional: Custom pages
pages: {
signIn: '/auth/login',
error: '/auth/error',
verifyRequest: '/auth/verify-email',
},
};
export const { auth, handlers, signIn, signOut } = createAuth(authConfig);4. Setup API Routes
Create app/api/auth/[...nextauth]/route.ts:
import { handlers } from '@/lib/auth';
export const { GET, POST } = handlers;5. Setup Middleware
Create middleware.ts:
import { createAuthMiddleware, AuthMiddlewareConfig } from '@webdevarif/auth';
import { authConfig } from '@/lib/auth';
const middlewareConfig: AuthMiddlewareConfig = {
protectedRoutes: ['/dashboard', '/profile'],
authRoutes: ['/auth/login', '/auth/register'],
publicRoutes: ['/', '/about', '/contact'],
apiRoutes: ['/api'],
defaultLoginRedirect: '/dashboard',
loginPath: '/auth/login',
};
export default createAuthMiddleware(authConfig, middlewareConfig);
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};6. Create Authentication Pages
Create app/auth/login/page.tsx:
'use client';
import { LoginPage } from '@webdevarif/auth';
import { authConfig } from '@/lib/auth';
export default function Login() {
return (
<LoginPage
config={authConfig}
onSubmit={async (values) => {
// Custom login logic
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(values),
});
return response.json();
}}
translations={{
title: 'Sign In',
description: 'Welcome back!',
fields: {
username: 'Email or Username',
password: 'Password',
},
}}
/>
);
}Create app/auth/register/page.tsx:
'use client';
import { RegisterPage } from '@webdevarif/auth';
import { authConfig } from '@/lib/auth';
export default function Register() {
return (
<RegisterPage
config={authConfig}
onSubmit={async (values) => {
// Custom registration logic
const response = await fetch('/api/auth/register', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(values),
});
return response.json();
}}
plans={[
{ handle: 'FREE', name: 'Free', price: 0, description: 'Basic features' },
{ handle: 'PRO', name: 'Pro', price: 29, description: 'All features' },
]}
translations={{
title: 'Create Account',
description: 'Join us today!',
}}
/>
);
}7. Use Authentication Hooks
'use client';
import { useAuth, useRole, useIsSuperuser } from '@webdevarif/auth';
export default function Dashboard() {
const { user, isAuthenticated, isLoading } = useAuth();
const isAdmin = useRole('ADMIN');
const isSuperuser = useIsSuperuser();
if (isLoading) return <div>Loading...</div>;
if (!isAuthenticated) return <div>Please log in</div>;
return (
<div>
<h1>Welcome, {user?.name}!</h1>
{isAdmin && <p>Admin Panel</p>}
{isSuperuser && <p>Superuser Access</p>}
</div>
);
}API Reference
Components
LoginForm
A customizable login form component.
<LoginForm
onSubmit={(values) => Promise<{success: boolean, error?: string}>}
onSuccess={() => void}
onError={(error: string) => void}
redirectTo="/dashboard"
showResendVerification={true}
onResendVerification={(identifier) => Promise<{success: boolean}>}
translations={object}
/>RegisterForm
A customizable single-step registration form similar to Clerk.
<RegisterForm
onSubmit={(values) => Promise<{success: boolean, error?: string}>}
onSuccess={() => void}
onError={(error: string) => void}
fields={[
{
name: 'name',
label: 'Full Name',
placeholder: 'John Doe',
type: 'text',
required: true,
},
{
name: 'username',
label: 'Username',
placeholder: 'johndoe',
type: 'text',
required: true,
uniquenessCheck: async (value) => {
const response = await fetch(`/api/check-username?value=${value}`);
return response.json();
},
},
{
name: 'email',
label: 'Email',
placeholder: '[email protected]',
type: 'email',
required: true,
uniquenessCheck: async (value) => {
const response = await fetch(`/api/check-email?value=${value}`);
return response.json();
},
},
{
name: 'password',
label: 'Password',
placeholder: 'Enter your password',
type: 'password',
required: true,
},
{
name: 'confirmPassword',
label: 'Confirm Password',
placeholder: 'Confirm your password',
type: 'password',
required: true,
},
]}
translations={object}
onCheckUniqueness={object}
/>ForgotPasswordForm
A form for requesting password reset emails.
<ForgotPasswordForm
onSubmit={(values) => Promise<{success: boolean, error?: string}>}
onSuccess={() => void}
onError={(error: string) => void}
onBackToLogin={() => void}
translations={object}
/>ResetPasswordForm
A form for resetting passwords with a token.
<ResetPasswordForm
onSubmit={(values) => Promise<{success: boolean, error?: string}>}
onSuccess={() => void}
onError={(error: string) => void}
token="reset-token"
translations={object}
/>ChangePasswordForm
A form for changing passwords (requires current password).
<ChangePasswordForm
onSubmit={(values) => Promise<{success: boolean, error?: string}>}
onSuccess={() => void}
onError={(error: string) => void}
translations={object}
/>VerifyEmailForm
A form for email verification with resend functionality.
<VerifyEmailForm
onSubmit={(values) => Promise<{success: boolean, error?: string}>}
onSuccess={() => void}
onError={(error: string) => void}
onResendVerification={() => Promise<{success: boolean}>}
token="verification-token"
email="[email protected]"
translations={object}
/>UpdateProfileForm
A form for updating user profile information.
<UpdateProfileForm
onSubmit={(values) => Promise<{success: boolean, error?: string}>}
onSuccess={() => void}
onError={(error: string) => void}
initialValues={object}
translations={object}
onCheckUniqueness={object}
/>Page Components
Complete page components with layout for all forms:
LoginPage&RegisterPageForgotPasswordPage&ResetPasswordPageChangePasswordPage&VerifyEmailPageUpdateProfilePage
Hooks
useAuth()
Returns authentication state and user information.
const { user, session, isAuthenticated, isLoading, isError, error } = useAuth();useRole(role: string)
Checks if the current user has a specific role.
const isAdmin = useRole('ADMIN');useIsSuperuser()
Checks if the current user is a superuser.
const isSuperuser = useIsSuperuser();usePlan(plan: string)
Checks if the current user has a specific plan.
const isPro = usePlan('PRO');useIsActive()
Checks if the current user account is active.
const isActive = useIsActive();Services
AuthService
Core authentication service with database operations.
import { AuthService } from '@webdevarif/auth';
// Initialize with database URL
AuthService.initialize(process.env.DATABASE_URL!);
// Get user by identifier
const user = await AuthService.getUserByIdentifier('[email protected]');
// Create new user
const result = await AuthService.createUser({
name: 'John Doe',
username: 'johndoe',
email: '[email protected]',
password: 'password123',
phone: '+1234567890',
});
// Verify credentials
const authResult = await AuthService.verifyCredentials('username', 'password');Middleware
createAuthMiddleware(config, middlewareConfig)
Creates authentication middleware for route protection.
const middleware = createAuthMiddleware(authConfig, {
protectedRoutes: ['/dashboard'],
authRoutes: ['/auth/login'],
publicRoutes: ['/'],
apiRoutes: ['/api'],
defaultLoginRedirect: '/dashboard',
loginPath: '/auth/login',
});Configuration
AuthConfig Interface
interface AuthConfig {
// Required
databaseUrl: string;
nextAuthSecret: string;
nextAuthUrl: string;
// Optional
google?: {
clientId: string;
clientSecret: string;
};
email?: {
from: string;
server: {
host: string;
port: number;
auth: {
user: string;
pass: string;
};
};
};
pages?: {
signIn?: string;
error?: string;
verifyRequest?: string;
};
callbacks?: {
signIn?: (params: {user: AuthUser, account: any}) => boolean | Promise<boolean>;
jwt?: (params: {token: any, user: AuthUser, account: any}) => any;
session?: (params: {session: AuthSession, token: any}) => AuthSession;
};
events?: {
linkAccount?: (params: {user: AuthUser, account: any}) => void | Promise<void>;
};
}Customization
Custom Styling
The package uses Tailwind CSS classes. You can customize the appearance by:
- Overriding CSS classes in your global styles
- Using the
classNameprop on components - Creating custom themes with Tailwind configuration
Custom Translations
All text is customizable through the translations prop:
const translations = {
title: 'Custom Login Title',
description: 'Custom description',
fields: {
username: 'Custom Username Label',
password: 'Custom Password Label',
},
submit: 'Custom Submit Button',
// ... more translations
};Custom Validation
You can provide custom validation functions:
<RegisterForm
onCheckUniqueness={{
username: async (value) => {
const response = await fetch(`/api/check-username?value=${value}`);
return response.json();
},
email: async (value) => {
const response = await fetch(`/api/check-email?value=${value}`);
return response.json();
},
}}
/>Examples
Check out the examples directory for complete implementation examples:
Contributing
Contributions are welcome! Please read our Contributing Guide for details.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
Changelog
See CHANGELOG.md for a list of changes and version history.
