vista-auth
v1.2.13
Published
Simple, powerful, and secure authentication for React apps - works with any framework
Downloads
126
Maintainers
Readme
🔐 Vista Auth
Simple, powerful, and secure authentication for React apps
Works with any framework • Any database • Zero configuration needed
Quick Start • Documentation • Examples • GitHub
✨ Why Vista Auth?
Vista Auth is a lightweight, production-ready authentication solution that takes 5 minutes to set up and works with any React framework and any database.
Key Features
- 🚀 Universal Compatibility - Works with Next.js (App & Pages), Remix, Vite, CRA, Express
- ☁️ Edge Runtime Ready - Runs on Cloudflare Workers, Vercel Edge, and Middleware (powered by
jose) - 💾 Database Agnostic - Prisma, MongoDB, Supabase, PostgreSQL, Firebase, or in-memory
- 🔒 Production-Ready Security - bcrypt hashing, JWT tokens, secure sessions
- 🔑 OAuth Built-in - Google, GitHub, Facebook, Microsoft, Apple providers included
- 🎯 Minimal Code - 150 lines vs 500+ lines of other solutions
- 🕵️ Built-in RBAC - Role-based access control with route guards and middleware
- ⚡ Real-Time Sync - WebSocket support for multi-tab/device synchronization
- 🌐 Offline Support - IndexedDB fallback for offline authentication
- 🎨 Pre-built UI - Professional Login/Signup pages with "Powered by VistaAuth" branding
- 📦 CLI Auto-Setup - One command to get started with provider setup helpers
- 🔧 Zero Config Required - Sensible defaults, customize when needed
📦 Installation
npm install vista-authyarn add vista-authpnpm add vista-auth🛠️ CLI Commands
Vista Auth includes a comprehensive CLI to help with setup and provide guidance:
Basic Commands
# Initialize new project with interactive setup
npx vista-auth init
# Generate secure authentication secret
npx vista-auth generate-secret
# Show all available commands
npx vista-auth --helpDetailed Help Topics
# Get help with API routes and authentication flow
npx vista-auth --help api
# Learn middleware setup for all frameworks
npx vista-auth --help middleware
# Cookie management and security guidelines
npx vista-auth --help cookies
# Database setup and adapter configuration
npx vista-auth --help database
# Complete implementation examples
npx vista-auth --help examplesWhat Each Help Topic Covers
--help api: Complete API route examples for login, logout, session management with Next.js, Express, and Remix--help middleware: Framework-specific middleware setup for Next.js App Router, Express, Remix, and React Router--help cookies: Cookie security best practices, debugging, and authentication flow management--help database: Database adapter setup for Prisma, MongoDB, Supabase, PostgreSQL, Firebase, and Memory--help examples: Full implementation examples with 5-minute setup guides for each framework
🚀 Quick Start
Step 1: Initialize with CLI
Run the interactive setup wizard:
npx vista-auth initThis creates:
- ✅
vista-auth.config.js- Server configuration - ✅
app/api/auth/route.js- API endpoints - ✅
providers.jsx- Client provider setup - ✅ Example components
Step 2: Wrap Your App
Next.js App Router:
// app/layout.tsx
import { AuthProvider } from "vista-auth/client";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<AuthProvider apiEndpoint="/api/auth">{children}</AuthProvider>
</body>
</html>
);
}Next.js Pages Router:
// pages/_app.tsx
import { AuthProvider } from "vista-auth/client";
import type { AppProps } from "next/app";
export default function App({ Component, pageProps }: AppProps) {
return (
<AuthProvider apiEndpoint="/api/auth">
<Component {...pageProps} />
</AuthProvider>
);
}Vite:
// src/main.tsx
import { AuthProvider } from "vista-auth/client";
ReactDOM.createRoot(document.getElementById("root")!).render(
<AuthProvider apiEndpoint="http://localhost:5173/api/auth">
<App />
</AuthProvider>
);Create React App (CRA):
// src/index.tsx
import { AuthProvider } from "vista-auth/client";
ReactDOM.createRoot(document.getElementById("root")!).render(
<AuthProvider apiEndpoint="http://localhost:3000/api/auth">
<App />
</AuthProvider>
);Step 3: Create Auth API Route
Next.js (App Router):
// app/api/auth/[...vista]/route.ts
import { auth } from "@/vista-auth.config";
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest) {
const { action, ...data } = await request.json();
let result;
switch (action) {
case "signIn":
result = await auth.signIn(data);
break;
case "signUp":
result = await auth.signUp(data);
break;
case "signOut":
// For signOut, we might need the token from the header/cookie
const token = request.cookies.get("vista-auth-token")?.value;
if (token) {
result = await auth.signOut(token);
} else {
result = { success: true };
}
break;
default:
return NextResponse.json(
{ success: false, error: "Invalid action" },
{ status: 400 }
);
}
const response = NextResponse.json(result);
// Set Secure Cookie if login/signup successful
if (result.success && result.data?.cookie) {
response.headers.append("Set-Cookie", result.data.cookie);
}
// Clear cookie on sign out
if (action === "signOut") {
response.cookies.delete("vista-auth-token");
}
return response;
}
export async function GET(request: NextRequest) {
const token = request.cookies.get("vista-auth-token")?.value;
if (!token) {
return NextResponse.json({ success: false, error: "No token" }, { status: 401 });
}
return NextResponse.json(await auth.getSession(token));
}Express:
// server.js
import express from "express";
import cookieParser from "cookie-parser";
import { auth } from "./vista-auth.config";
const app = express();
app.use(express.json());
app.use(cookieParser());
app.post("/api/auth", async (req, res) => {
const { action, ...data } = req.body;
let result;
switch (action) {
case "signIn":
result = await auth.signIn(data);
break;
case "signUp":
result = await auth.signUp(data);
break;
case "signOut":
const token = req.cookies["vista-auth-token"];
if (token) await auth.signOut(token);
res.clearCookie("vista-auth-token");
return res.json({ success: true });
case "getSession":
// ...
break;
}
if (result?.success && result.data?.cookie) {
res.setHeader("Set-Cookie", result.data.cookie);
}
res.json(result);
});🛡️ Middleware
Automatic Generation (Recommended)
When you run npx vista-auth init, the CLI will automatically generate the correct middleware file for your selected framework (Next.js middleware.ts or Express auth-middleware.ts).
Manual Setup
Next.js Middleware:
import { createNextMiddleware } from "vista-auth/middleware";
export default createNextMiddleware({
publicPaths: ["/login", "/signup", "/", "/about"],
roleBasedPaths: {
"/admin/*": ["admin"],
"/dashboard/*": ["user", "admin"],
},
// jwtSecret is now automatically picked up from your config/env
});
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};Express Middleware
import express from "express";
import { createExpressMiddleware } from "vista-auth/middleware";
const app = express();
const authMiddleware = createExpressMiddleware({
publicPaths: ["/login", "/signup", "/api/public/*"],
jwtSecret: process.env.VISTA_AUTH_SECRET,
});
app.use(authMiddleware);
app.get("/api/protected", (req, res) => {
res.json({ message: "Protected data", user: req.user });
});🔑 OAuth Providers
Vista Auth supports major OAuth providers out of the box with minimal setup.
Supported Providers
- ✅ Google - OAuth 2.0
- ✅ GitHub - OAuth 2.0
- ✅ Facebook - OAuth 2.0
- ✅ Microsoft - OAuth 2.0 (Azure AD)
- ✅ Apple - Sign in with Apple
Quick Setup
Use the CLI to get your OAuth credentials:
npx vista-auth setup-provider google
npx vista-auth setup-provider githubUsage Example
import { GoogleProvider, GitHubProvider } from "vista-auth/providers";
import { createVistaAuth } from "vista-auth/server";
export const auth = createVistaAuth({
jwtSecret: process.env.VISTA_AUTH_SECRET,
});
// In your OAuth callback route
const googleProvider = new GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
redirectUri: "http://localhost:3000/api/auth/callback/google",
});
// Exchange code for user profile
const profile = await googleProvider.verify(code);
// Create session
const result = await auth.loginWithProvider({
email: profile.email,
name: profile.name,
image: profile.image,
provider: "google",
providerId: profile.id,
});🎨 Pre-built UI Components
Vista Auth includes professional, customizable UI components.
AuthPage - Complete Login/Signup Page
A beautiful, production-ready authentication page with email/password and social login support.
import { AuthPage } from "vista-auth/ui";
import { createVistaAuth } from "vista-auth/server";
import { redirect } from "next/navigation";
import { cookies } from "next/headers";
const auth = createVistaAuth({ jwtSecret: process.env.VISTA_AUTH_SECRET });
export default function LoginPage() {
async function handleSignIn(formData: any) {
"use server";
const result = await auth.signIn({
email: formData.email,
password: formData.password,
});
if (result.success && result.data) {
(await cookies()).set("vista-auth-token", result.data.token);
redirect("/dashboard");
}
}
async function handleSignUp(formData: any) {
"use server";
const result = await auth.signUp({
email: formData.email,
password: formData.password,
name: formData.name,
});
if (result.success && result.data) {
(await cookies()).set("vista-auth-token", result.data.token);
redirect("/dashboard");
}
}
return (
<AuthPage
appName="My App"
onSignIn={handleSignIn}
onSignUp={handleSignUp}
// Optional: Add social login buttons
socialButtons={
<div className="grid grid-cols-2 gap-3">
<button>Google</button>
<button>GitHub</button>
</div>
}
/>
);
}Features:
- ✨ Professional design with dark mode support
- 🔄 Automatic toggle between Login/Signup
- ⚡ Built-in loading states and error handling
- 🎨 Fully customizable with Tailwind CSS
- 🏷️ "Powered by VistaAuth" branding
Toast Notifications
import { showToast, showError, showWarning, showInfo } from "vista-auth/ui";
showToast("Login successful!", 3000);
showError("Invalid credentials");
showWarning("Session expiring soon");
showInfo("New features available");🔄 Real-Time Session Sync
Synchronize authentication state across multiple tabs and devices:
<AuthProvider
apiEndpoint="/api/auth"
config={{
sessionSyncEnabled: true,
websocketUrl: "wss://your-domain.com/ws/auth",
}}
>
{children}
</AuthProvider>🌐 Offline Support
Vista Auth supports offline authentication with IndexedDB:
<AuthProvider
config={{
sessionStorage: "indexedDB",
offlineFallback: true,
}}
>
{children}
</AuthProvider>🔧 API Reference
Client Hooks
useAuth()
const {
// State
user, // Current user object or null
session, // Current session object or null
isLoading, // true while checking authentication
isAuthenticated, // true if user is signed in
error, // Error message if any
// Actions
signIn, // (credentials) => Promise<void>
signUp, // (data) => Promise<void>
signOut, // () => Promise<void>
updateUser, // (data) => Promise<void>
// Role & Permission Checks
hasRole, // (role: string) => boolean
hasPermission, // (permission: string) => boolean
hasAnyRole, // (roles: string[]) => boolean
hasAllRoles, // (roles: string[]) => boolean
} = useAuth();Server API
createVistaAuth(config)
import { createVistaAuth } from "vista-auth/server";
const auth = createVistaAuth({
database: adapter, // Database adapter or null
jwtSecret: string, // Secret for JWT signing
bcryptRounds: number, // bcrypt cost factor (default: 10)
sessionDuration: number, // Session duration in ms
});
// Methods
await auth.signUp({ email, password, name, roles, permissions });
await auth.signIn({ email, password });
await auth.getSession(token);
await auth.signOut(sessionId);
await auth.hashPassword(password);
await auth.verifyPassword(password, hash);
auth.generateToken(payload);
auth.verifyToken(token);💡 Complete Examples
Full Login Page with Validation
"use client";
import { useState } from "react";
import { useAuth } from "vista-auth/client";
import { showError, showToast } from "vista-auth/ui";
export default function LoginPage() {
const { signIn, signUp, isLoading } = useAuth();
const [isSignUp, setIsSignUp] = useState(false);
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const formData = new FormData(e.currentTarget);
const email = formData.get("email") as string;
const password = formData.get("password") as string;
const name = formData.get("name") as string;
if (!email || !password) {
showError("Email and password are required");
return;
}
if (password.length < 8) {
showError("Password must be at least 8 characters");
return;
}
try {
if (isSignUp) {
await signUp({ email, password, name });
showToast("Account created successfully!");
} else {
await signIn({ email, password });
showToast("Welcome back!");
}
} catch (error) {
showError(error.message || "Authentication failed");
}
};
return (
<div className="min-h-screen flex items-center justify-center bg-gray-50">
<div className="max-w-md w-full space-y-8 p-8 bg-white rounded-lg shadow">
<h2 className="text-3xl font-bold text-center">
{isSignUp ? "Create Account" : "Sign In"}
</h2>
<form onSubmit={handleSubmit} className="space-y-6">
{isSignUp && (
<div>
<label htmlFor="name" className="block text-sm font-medium">
Name
</label>
<input
id="name"
name="name"
type="text"
className="mt-1 block w-full px-3 py-2 border rounded-md"
placeholder="John Doe"
/>
</div>
)}
<div>
<label htmlFor="email" className="block text-sm font-medium">
Email
</label>
<input
id="email"
name="email"
type="email"
required
className="mt-1 block w-full px-3 py-2 border rounded-md"
placeholder="[email protected]"
/>
</div>
<div>
<label htmlFor="password" className="block text-sm font-medium">
Password
</label>
<input
id="password"
name="password"
type="password"
required
className="mt-1 block w-full px-3 py-2 border rounded-md"
placeholder="••••••••"
/>
</div>
<button
type="submit"
disabled={isLoading}
className="w-full py-2 px-4 rounded-md text-white bg-blue-600 hover:bg-blue-700 disabled:opacity-50"
>
{isLoading ? "Loading..." : isSignUp ? "Sign Up" : "Sign In"}
</button>
</form>
<div className="text-center">
<button
onClick={() => setIsSignUp(!isSignUp)}
className="text-sm text-blue-600 hover:text-blue-500"
>
{isSignUp
? "Already have an account? Sign in"
: "Don't have an account? Sign up"}
</button>
</div>
</div>
</div>
);
}Protected Dashboard
"use client";
import { useAuth } from "vista-auth/client";
import { useRequireAuth } from "vista-auth/guards";
import { showToast } from "vista-auth/ui";
export default function DashboardPage() {
useRequireAuth("/login");
const { user, signOut, hasRole, hasPermission } = useAuth();
const handleSignOut = async () => {
await signOut();
showToast("Signed out successfully");
};
return (
<div className="min-h-screen bg-gray-100">
<nav className="bg-white shadow">
<div className="max-w-7xl mx-auto px-4 py-4 flex justify-between items-center">
<h1 className="text-2xl font-bold">Dashboard</h1>
<button
onClick={handleSignOut}
className="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700"
>
Sign Out
</button>
</div>
</nav>
<main className="max-w-7xl mx-auto px-4 py-8">
<div className="bg-white rounded-lg shadow p-6 mb-6">
<h2 className="text-xl font-semibold mb-4">Welcome, {user?.name}!</h2>
<p className="text-gray-600">Email: {user?.email}</p>
<p className="text-gray-600">
Roles: {user?.roles?.join(", ") || "None"}
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{hasPermission("posts:view") && (
<div className="bg-white rounded-lg shadow p-6">
<h3 className="text-lg font-semibold mb-2">Posts</h3>
<p className="text-gray-600">Manage your posts</p>
</div>
)}
{hasRole("admin") && (
<div className="bg-white rounded-lg shadow p-6">
<h3 className="text-lg font-semibold mb-2">Admin Panel</h3>
<p className="text-gray-600">System administration</p>
</div>
)}
</div>
</main>
</div>
);
}🛠️ Configuration
Full Configuration Example
// vista-auth.config.ts
import { createVistaAuth } from "vista-auth/server";
import { createPrismaAdapter } from "vista-auth/database";
import { prisma } from "./lib/prisma";
export const auth = createVistaAuth({
// Database adapter (optional)
database: createPrismaAdapter(prisma),
// Security settings
jwtSecret: process.env.VISTA_AUTH_SECRET!,
bcryptRounds: 12,
sessionDuration: 7 * 24 * 60 * 60 * 1000, // 7 days
// Lifecycle callbacks
onSignIn: (user) => {
console.log("User signed in:", user.email);
},
onSignOut: () => {
console.log("User signed out");
},
onSessionExpired: () => {
console.log("Session expired");
},
onError: (error) => {
console.error("Auth error:", error);
},
});Environment Variables
Create a .env.local file:
# Required: Secret for JWT signing
VISTA_AUTH_SECRET=your-super-secret-jwt-key-change-in-production
# Optional: Database connection
DATABASE_URL=postgresql://user:password@localhost:5432/myapp
# Optional: WebSocket URL
NEXT_PUBLIC_WS_URL=wss://your-domain.com/ws/auth🔒 Security Features
- ✅ bcrypt hashing with configurable cost factor
- ✅ JWT tokens with expiration
- ✅ Secure session management
- ✅ CSRF protection ready
- ✅ XSS protection
- ✅ Rate limiting ready
- ✅ Environment variable secrets
📊 Comparison with Other Solutions
| Feature | Vista Auth | NextAuth.js | Clerk | Auth0 | | -------------------------- | ---------- | ----------- | ------ | ------ | | Setup Time | 5 minutes | 30+ minutes | 15 min | 20 min | | Lines of Code | ~150 | 500+ | 200+ | 300+ | | Works Without Database | ✅ | ❌ | ❌ | ✅ | | Database Agnostic | ✅ | ⚠️ | ❌ | ✅ | | Framework Agnostic | ✅ | ❌ | ⚠️ | ✅ | | Built-in RBAC | ✅ | ❌ | ✅ | ✅ | | Real-Time Sync | ✅ | ❌ | ✅ | ✅ | | Offline Support | ✅ | ❌ | ❌ | ❌ | | UI Components | ✅ | ❌ | ✅ | ✅ | | Bundle Size | ~5KB | ~50KB | ~80KB | ~100KB | | Pricing | Free | Free | Paid | Paid | | Self-Hosted | ✅ | ✅ | ❌ | ❌ | | TypeScript First | ✅ | ⚠️ | ✅ | ✅ | | CLI Tool | ✅ | ❌ | ✅ | ❌ |
🤝 Contributing
We welcome contributions from everyone! 🎉
Quick Start for Contributors
- ⭐ Star the repository
- 🍴 Fork the project
- 🔍 Find an issue labeled
good first issueorhelp wanted - 💻 Make your changes
- 📝 Submit a pull request
Ways to Contribute
- 🐛 Report bugs - Found an issue? Let us know!
- ✨ Suggest features - Have an idea? We'd love to hear it!
- 📖 Improve docs - Help others understand Vista Auth better
- 🧪 Write tests - Increase code coverage
- 🔧 Fix bugs - Help squash those pesky bugs
- 🎨 Add examples - Show others how to use Vista Auth
Get Started
- Contributing Guide - Complete guide for contributors
- Contribution Program - Recognition, rewards, and opportunities
- Code of Conduct - Our community guidelines
- Open Issues - Find something to work on
Recognition
All contributors are recognized in our README and release notes. Significant contributors receive swag and special recognition! 🏆
Join our growing community of contributors! We can't wait to see what you'll build! 💪
📄 License
MIT © Vista Auth
🌟 Why Choose Vista Auth?
- Simplicity - 150 lines vs 500+ in alternatives
- Flexibility - Works with any React framework and database
- Power - Built-in RBAC, real-time sync, offline support
- Security - Production-ready with bcrypt and JWT
- Developer Experience - TypeScript-first with great docs
📞 Support
- GitHub Issues: Report bugs or request features
- GitHub Discussions: Ask questions
- Documentation: Full docs
Ready to add authentication to your app?
npm install vista-auth
npx vista-auth init⭐ Star us on GitHub!
