@zewstid/nextjs
Official ZewstID SDK for Next.js - OAuth/OIDC authentication with ZewstID.
Current Version: v0.9.0 (February 2026)
v0.9.0: Adds Popup Sign-In and Embedded Sign-In components. See Popup Sign-In Guide and Embedded Sign-In Guide.
✨ Features
- 🔐 OAuth/OIDC - Standard OpenID Connect with ZewstID
- 🌐 12 Auth Methods - Password, magic links, OTP, WebAuthn, social login, MFA — all on auth.zewstid.com
- 🔄 Cross-Portal SSO - Automatic SSO via ZewstID session cookies
- 🎯 Type-Safe - Full TypeScript support
- 📦 Lightweight - Minimal footprint with tree-shaking
- 📱 Next.js 14/15 - Full App Router and Pages Router support
🚀 Installation
npm install @zewstid/nextjs next-auth
📖 Quick Start
1. Get Your Credentials
Sign up at developers.zewstid.com and create a new application to get your:
- Client ID
- Client Secret
2. Environment Variables
Create a
.env.localZEWSTID_CLIENT_ID=your_client_id ZEWSTID_CLIENT_SECRET=your_client_secret NEXTAUTH_SECRET=your_random_secret_min_32_chars NEXTAUTH_URL=http://localhost:3000
3. Create Auth Configuration
App Router (
app/api/auth/[...nextauth]/route.tsimport { createZewstIDAuth } from '@zewstid/nextjs'; import NextAuth from 'next-auth'; export const authOptions = createZewstIDAuth({ clientId: process.env.ZEWSTID_CLIENT_ID!, clientSecret: process.env.ZEWSTID_CLIENT_SECRET!, }); const handler = NextAuth(authOptions); export { handler as GET, handler as POST };
4. Wrap Your App
// app/layout.tsx import { ZewstIDProvider } from '@zewstid/nextjs'; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html> <body> <ZewstIDProvider> {children} </ZewstIDProvider> </body> </html> ); }
5. Add Sign In/Out Buttons
'use client'; import { signIn, signOut, useSession } from 'next-auth/react'; export function AuthButtons() { const { data: session } = useSession(); if (!session) { return ( <button onClick={() => signIn('zewstid')}> Sign in with ZewstID </button> ); } return ( <div> <p>Welcome {session.user?.name}!</p> <button onClick={() => signOut()}>Sign Out</button> </div> ); }
🔐 Authentication Flow
- User clicks "Sign in with ZewstID"
- Browser redirects to
auth.zewstid.com - User authenticates using any of 12 methods
- Browser redirects back with authorization code
- NextAuth exchanges code for tokens
- Session is created in your app
🛡️ Protecting Routes
Middleware Protection
// middleware.ts import { withZewstIDAuth } from '@zewstid/nextjs/middleware'; export default withZewstIDAuth({ protectedPaths: ['/dashboard', '/settings'], signInPath: '/api/auth/signin', }); export const config = { matcher: ['/dashboard/:path*', '/settings/:path*'], };
Server Component Protection
// app/dashboard/page.tsx import { getServerSession } from 'next-auth'; import { authOptions } from '@/app/api/auth/[...nextauth]/route'; import { redirect } from 'next/navigation'; export default async function DashboardPage() { const session = await getServerSession(authOptions); if (!session) { redirect('/api/auth/signin'); } return <div>Welcome {session.user?.name}!</div>; }
🔑 Role-Based Access Control
import { useRBAC, RBACProvider } from '@zewstid/nextjs'; const rolePermissions = { admin: [{ resource: '*', action: '*' }], editor: [{ resource: 'posts', action: '*' }], viewer: [{ resource: 'posts', action: 'read' }], }; // Wrap your app <RBACProvider clientId="my-app" rolePermissions={rolePermissions}> {children} </RBACProvider> // Use in components function AdminPanel() { const { hasRole } = useRBAC(); if (!hasRole('admin')) { return <p>Access denied</p>; } return <div>Admin Panel</div>; }
🚪 Logout
For proper logout that clears both NextAuth and ZewstID sessions:
// app/api/auth/logout/route.ts import { createLogoutHandler } from '@zewstid/nextjs/handlers'; import { authOptions } from '../[...nextauth]/route'; export const GET = createLogoutHandler(authOptions, { postLogoutRedirectUri: process.env.NEXTAUTH_URL, });
// In your component <a href="/api/auth/logout">Sign Out</a>
📦 API Reference
Main Exports (@zewstid/nextjs)
@zewstid/nextjs| Export | Description |
|---|---|
createZewstIDAuth() | Create NextAuth configuration |
ZewstIDProvider | Session provider wrapper |
getZewstIDCallbacks() | NextAuth callbacks for token handling |
useZewstID() | Hook for auth state |
useRBAC() | Hook for role-based access |
RBACProvider | RBAC context provider |
PopupSignIn | Popup-based sign-in button (guide) |
PopupCallback | Popup callback page component |
EmbeddedSignIn | Clerk-style inline sign-in form (guide) |
UserButton | User avatar dropdown with sign out |
Handlers (@zewstid/nextjs/handlers)
@zewstid/nextjs/handlers| Export | Description |
|---|---|
createLogoutHandler() | Logout with ZewstID session end |
createPostLogoutHandler() | Post-logout redirect handler |
Middleware (@zewstid/nextjs/middleware)
@zewstid/nextjs/middleware| Export | Description |
|---|---|
withZewstIDAuth() | Middleware for route protection |
createClientMiddleware() | Custom middleware creator |
🔄 Migrating from v0.7.x to v0.9.0
v0.8.0 removed ROPC-based embedded authentication. v0.9.0 re-introduces embedded auth using new, secure components.
What Was Removed in v0.8.0
// ❌ These no longer work import { createZewstIDHandlers } from '@zewstid/nextjs/handlers'; // REMOVED import { SignIn } from '@zewstid/nextjs'; // Old component removed // ❌ These methods throw errors await client.signInWithPassword(email, password); // Throws await client.verifyMagicLink(token); // Throws await client.verifyOTP(email, code); // Throws
What's New in v0.9.0
// ✅ New components (replace old <SignIn />) import { PopupSignIn, PopupCallback, EmbeddedSignIn, UserButton } from '@zewstid/nextjs/components';
Migration Steps
- Remove ROPC handlers: Delete
app/api/zewstid/[...zewstid]/route.ts - Replace : Use one of:
<SignIn />- — redirect (simplest)
signIn('zewstid') - — popup window (Auth0 Lock-style)
<PopupSignIn /> - — inline form (Clerk-style)
<EmbeddedSignIn />
- Remove : SSO works automatically via ZewstID session
enableSSOEstablishment - Update logout: Use for proper session cleanup
createLogoutHandler()
🆘 Support
Was this page helpful?
Let us know how we can improve our documentation