Skip to main content

Onboarding a New Application to ZewstID

This guide covers the complete process of adding a new application to the ZewstID authentication system.

Google Model (February 2026): All applications now integrate via OAuth redirect to

auth.zewstid.com
. Users authenticate on ZewstID's login page and are redirected back to your application. This is the same pattern used by Google, Microsoft, and Okta.


Overview

Integration Approach: Standard OAuth 2.0 / OpenID Connect redirect flow.

Authentication Methods: Users can choose from 12 methods on the ZewstID login page:

  • Email/Password
  • Magic Links
  • OTP (email/SMS)
  • WebAuthn/Passkeys
  • Social Login (Google, GitHub, Microsoft, Apple, Facebook)
  • MFA (TOTP, Push)

Who does what:

  • ZewstID Admin (us): Configure OAuth client, assign roles
  • App Team (them): Install SDK or OAuth library, integrate authentication

Timeline: ~30 minutes for setup + integration time for app team


Quick Start

npm install @zewstid/nextjs next-auth
// app/api/auth/[...nextauth]/route.ts import { 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 };

For Other Frameworks

Use any OAuth/OIDC library with these settings:

Discovery URL: https://auth.zewstid.com/.well-known/openid-configuration Issuer URL: Available in Developer Portal → App Settings

See OAuth Integration Guide for complete examples with React, Express, Flask, and more.


Part 1: Admin Setup (ZewstID Team)

Step 1: Create OAuth Client

Go to Admin DashboardOAuth ClientsCreate Client

Fill in:

FieldDescriptionExample
Client IDUnique identifier
my-app
Client NameDisplay name
My Application
Client TypeWeb, SPA, Mobile, or M2M
Web
Redirect URIsWhere to redirect after auth
https://myapp.com/api/auth/callback/zewstid
Post-Logout URIsWhere to redirect after logout
https://myapp.com

Step 2: Configure Client Settings

Set these options:

  • Standard Flow Enabled: Yes (authorization code flow)
  • Direct Access Grants Enabled: No (ROPC not needed)
  • Service Accounts Enabled: Only if using M2M
  • PKCE: Required for SPAs/Mobile

Step 3: Assign Roles (Optional)

If your app uses role-based access:

  1. Go to RolesCreate Role
  2. Name your roles (e.g.,
    admin
    ,
    editor
    ,
    viewer
    )
  3. Assign roles to users via UsersRole Mappings

Part 2: App Integration

Step 1: Environment Variables

# Required ZEWSTID_CLIENT_ID=your_client_id ZEWSTID_CLIENT_SECRET=your_client_secret # NextAuth NEXTAUTH_SECRET=random_secret_min_32_chars NEXTAUTH_URL=https://your-app.com

Step 2: Create Auth Configuration

Next.js with @zewstid/nextjs:

// app/api/auth/[...nextauth]/route.ts import { 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 };

Next.js with plain NextAuth:

// app/api/auth/[...nextauth]/route.ts import NextAuth from 'next-auth'; export const authOptions = { providers: [ { id: 'zewstid', name: 'ZewstID', type: 'oidc', clientId: process.env.ZEWSTID_CLIENT_ID!, clientSecret: process.env.ZEWSTID_CLIENT_SECRET!, issuer: process.env.ZEWSTID_ISSUER_URL!, }, ], }; const handler = NextAuth(authOptions); export { handler as GET, handler as POST };

Step 3: Add Provider Wrapper

// app/layout.tsx import { ZewstIDProvider } from '@zewstid/nextjs'; // Or: import { SessionProvider } from 'next-auth/react'; export default function RootLayout({ children }) { return ( <html> <body> <ZewstIDProvider> {children} </ZewstIDProvider> </body> </html> ); }

Step 4: Add Sign In Button

'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> ); }

Part 3: Testing

Test the Flow

  1. Click "Sign in with ZewstID"
  2. You should be redirected to
    auth.zewstid.com
  3. Sign in with any supported method
  4. You should be redirected back to your app with a session

Verify Token Contents

Check that your token contains the expected claims:

import { getServerSession } from 'next-auth'; const session = await getServerSession(authOptions); console.log('User:', session?.user); console.log('Roles:', session?.roles);

Part 4: Role-Based Access (Optional)

If you assigned roles in Part 1:

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> // Check permissions function AdminPanel() { const { hasRole } = useRBAC(); if (!hasRole('admin')) { return <p>Access denied</p>; } return <div>Admin Panel</div>; }

Troubleshooting

"Invalid redirect_uri" Error

Your redirect URI must exactly match what's configured in the OAuth client:

  • Check for trailing slashes
  • Check http vs https
  • Check port numbers

Session Not Persisting

Make sure

NEXTAUTH_SECRET
is set and at least 32 characters.

Roles Not in Token

  1. Check role assignments in Admin Dashboard
  2. Verify the StandardRolesMapper is enabled on the client

Next Steps

Was this page helpful?

Let us know how we can improve our documentation