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.


Overview

ZewstID supports two integration tracks:

TrackForFeatures
Track AInternal Zewst apps (Zeye, ZPos, ZewstPay, etc.)Full cross-portal SSO, custom login UI, all auth methods
Track BThird-party / external appsStandard OAuth/OIDC, no cross-portal SSO

Who does what:

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

Timeline: ~1-2 hours for setup + integration time for app team


Determine the Integration Track

Track A: Internal Zewst Ecosystem Apps

Use Track A if:

  • Application is a first-party Zewst product
  • Needs cross-portal SSO (user logs into one app, automatically logged into all)
  • Wants custom login UI with password, OTP, magic link support
  • Will use the
    @zewstid/nextjs
    SDK with
    enableSSOEstablishment: true

Examples: User Portal, Developer Portal, Admin Dashboard, Zeye, ZPos, ZewstPay

Track B: Third-Party / External Apps

Use Track B if:

  • Application is built by external developers or partners
  • Standard OAuth redirect flow is acceptable
  • No need for cross-portal SSO with Zewst apps
  • Can use any OAuth library (NextAuth, Passport, oidc-client-ts, etc.)

Examples: Partner integrations, customer apps, third-party tools


Part 0: Quick Reference by Track

Track A Setup (Internal Apps)

// app/api/zewstid/[...zewstid]/route.ts import { createZewstIDHandlers } from '@zewstid/nextjs/handlers'; const handlers = createZewstIDHandlers({ clientId: process.env.ZEWSTID_CLIENT_ID!, clientSecret: process.env.ZEWSTID_CLIENT_SECRET!, baseUrl: process.env.NEXTAUTH_URL, apiUrl: process.env.ZEWSTID_API_URL, issuerUrl: process.env.ZEWSTID_ISSUER_URL, enableSSOEstablishment: true, // Cross-portal SSO }); export const GET = handlers.GET; export const POST = handlers.POST;

Track B Setup (External Apps)

// 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: 'https://auth.zewstid.com/realms/zewstid', }, ], }; const handler = NextAuth(authOptions); export { handler as GET, handler as POST };

See OAuth Integration Guide for complete Track B examples with other frameworks.


Part 1: Admin Setup (ZewstID Team)

Step 1: Create OAuth Client

Use the ZewstID Admin Dashboard or API to create a new OAuth client:

# SSH to ZewstID server cd /opt/zewst-sso # Run client creation script ./scripts/create-oauth-client.sh

Provide:

  • Client ID:
    {app-name}-app
    (e.g.,
    zeye-app
    ,
    zpos-app
    ,
    zewstpay-app
    )
  • Client Name:
    {App Name}
    (e.g.,
    Zeye
    ,
    ZPos
    ,
    ZewstPay
    )
  • Root URL:
    https://{app-domain}.zewst.com
    (e.g.,
    https://zeye.zewst.com
    )
  • Valid Redirect URIs:
    • https://{app-domain}.zewst.com/api/auth/callback/zewstid
    • http://localhost:3000/api/auth/callback/zewstid
      (for dev)

Script creates:

  • OAuth2 client with PKCE enabled
  • Client secret (save this securely)
  • Confidential access type
  • Standard flow enabled

Alternative: Use the Admin Dashboard

  1. Go to https://admin.zewstid.com
  2. Navigate to ApplicationsCreate New
  3. Fill in the client details
  4. Save and securely store the client secret

Alternative: Use the API

curl -X POST https://api.zewstid.com/v1/clients \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "clientId": "zeye-app", "name": "Zeye", "redirectUris": [ "https://zeye.zewst.com/api/auth/callback/zewstid", "http://localhost:3000/api/auth/callback/zewstid" ], "pkceEnabled": true }'

Step 2: Define Client Roles

Based on the application's needs, define roles:

# Example: Zeye roles zeye-admin # Full admin access zeye-user # Standard user (can view/manage cameras) zeye-viewer # Read-only access # Example: ZPos roles zpos-admin # Full admin access zpos-manager # Manager access (reports, inventory) zpos-cashier # Cashier access (transactions only)

Create roles via API:

# Create zeye-admin role curl -X POST https://api.zewstid.com/v1/roles \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "zeye-admin", "description": "Zeye Administrator", "clientId": "zeye-app", "permissions": ["zeye.*"] }' # Create zeye-user role curl -X POST https://api.zewstid.com/v1/roles \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "zeye-user", "description": "Zeye Standard User", "clientId": "zeye-app", "permissions": ["zeye.cameras.view", "zeye.cameras.manage"] }' # Create zeye-viewer role curl -X POST https://api.zewstid.com/v1/roles \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "zeye-viewer", "description": "Zeye Viewer (Read-only)", "clientId": "zeye-app", "permissions": ["zeye.cameras.view"] }'

Or use Admin Dashboard:

  1. Go to https://admin.zewstid.com
  2. Navigate to RolesCreate New
  3. Select client:
    zeye-app
  4. Add each role with appropriate permissions

Custom claims are automatically included in JWT tokens for client-specific roles. The SDK handles this automatically.

Default token structure:

{ "sub": "user-id", "email": "user@example.com", "client_roles": { "zeye-app": ["zeye-user"] }, "permissions": ["zeye.cameras.view", "zeye.cameras.manage"] }

Step 4: Create Test Users

Create users for the app team to test with:

./scripts/create-test-users.sh zeye-app

This creates:

  • {app}-admin-user
    /
    password
    (with admin role)
  • {app}-standard-user
    /
    password
    (with standard user role)
  • {app}-viewer-user
    /
    password
    (with viewer role)

Or create via API:

# Create admin user curl -X POST https://api.zewstid.com/v1/users \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "email": "zeye-admin@test.com", "password": "password", "emailVerified": true, "roles": { "zeye-app": ["zeye-admin"] } }'

Or use Admin Dashboard:

  1. Go to UsersCreate New
  2. Fill in user details
  3. Navigate to Role Assignments
  4. Assign appropriate client roles

Step 5: Generate Integration Package

Prepare the handoff package for the app team:

# Get client secret via API CLIENT_SECRET=$(curl -X GET https://api.zewstid.com/v1/clients/zeye-app/secret \ -H "Authorization: Bearer $ADMIN_TOKEN" | jq -r '.secret') # Save to secure location echo "Client ID: zeye-app" > /secure/handoff-zeye.txt echo "Client Secret: $CLIENT_SECRET" >> /secure/handoff-zeye.txt

Part 2: Information to Share with App Team

Create a handoff document with:

2.1 Credentials & Configuration

# ZewstID Configuration for {App Name} # OAuth Configuration ZEWSTID_ISSUER_URL=https://auth.zewstid.com/realms/zewstid ZEWSTID_CLIENT_ID={app-name}-app ZEWSTID_CLIENT_SECRET={generated-secret} # NextAuth Configuration (for Next.js apps) NEXTAUTH_URL=https://{app-domain}.zewst.com NEXTAUTH_SECRET={generate-with: openssl rand -base64 32} # npm Registry (for @zewstid packages) NPM_REGISTRY=https://npm.zewstid.com/

2.2 Available Roles

RoleDescriptionTypical Use Case
{app}-admin
Full administrator accessSystem configuration, user management
{app}-user
Standard user accessNormal application usage
{app}-viewer
Read-only accessViewing data only

2.3 Test User Credentials

Admin User: Email: {app}-admin@test.com Password: password Roles: {app}-admin Standard User: Email: {app}-user@test.com Password: password Roles: {app}-user Viewer: Email: {app}-viewer@test.com Password: password Roles: {app}-viewer

2.4 SDK Information

# Install ZewstID SDK npm login --registry=https://npm.zewstid.com/ # (credentials provided separately) npm install @zewstid/nextjs

2.5 Key Endpoints

Authorization: https://auth.zewstid.com/realms/zewstid/protocol/openid-connect/auth Token: https://auth.zewstid.com/realms/zewstid/protocol/openid-connect/token UserInfo: https://auth.zewstid.com/realms/zewstid/protocol/openid-connect/userinfo JWKS: https://auth.zewstid.com/realms/zewstid/protocol/openid-connect/certs Logout: https://auth.zewstid.com/realms/zewstid/protocol/openid-connect/logout

Part 3: Developer Integration Guide (Share This)

The app team should follow the Quick Start Guide for step-by-step integration instructions.

This includes:

  • Step-by-step SDK installation
  • Authentication setup code
  • RBAC implementation examples
  • Route protection examples
  • API route protection examples
  • Testing instructions

Part 4: Admin Checklist

Use this checklist when onboarding a new app:

Pre-Onboarding

  • Get app details from team (name, domain, required roles)
  • Understand their user access patterns
  • Confirm development and production URLs

OAuth Client Configuration

  • Create OAuth2 client in ZewstID
  • Configure redirect URIs (prod + dev)
  • Generate and securely store client secret
  • Create client roles based on requirements
  • Verify token claims configuration
  • Create test users with appropriate roles
  • Test authentication flow with test users

Documentation & Handoff

  • Create handoff document with credentials
  • Share test user credentials
  • Provide npm registry access
  • Share developer integration guide
  • Schedule kickoff call with app team
  • Add to monitoring/logging

Post-Integration Support

  • Verify first successful authentication
  • Check token claims are correct
  • Validate RBAC is working
  • Set up production users
  • Document in internal wiki

Part 5: Troubleshooting Common Issues

Issue: "Invalid redirect_uri"

Cause: Redirect URI not whitelisted in client configuration Fix: Add URI to Valid Redirect URIs in Admin Dashboard or via API

curl -X PATCH https://api.zewstid.com/v1/clients/zeye-app \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "redirectUris": [ "https://zeye.zewst.com/api/auth/callback/zewstid", "http://localhost:3000/api/auth/callback/zewstid" ] }'

Issue: "Roles not appearing in token"

Cause: User doesn't have roles assigned Fix:

  1. Check role assignments in Admin Dashboard
  2. Verify user has client roles assigned
# Assign role to user via API curl -X POST https://api.zewstid.com/v1/users/{user-id}/roles \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "clientId": "zeye-app", "roles": ["zeye-user"] }'

Issue: "401 Unauthorized" in production

Cause: Wrong client secret or environment variables Fix: Verify

ZEWSTID_CLIENT_SECRET
matches the generated secret

# Retrieve client secret curl -X GET https://api.zewstid.com/v1/clients/zeye-app/secret \ -H "Authorization: Bearer $ADMIN_TOKEN"

Issue: "Cannot access private npm packages"

Cause: Not authenticated to Verdaccio Fix: Run

npm login --registry=https://npm.zewstid.com/


Part 6: Security Best Practices

For Admin (Us)

  1. Client Secrets: Store in password manager, never commit to git
  2. Test Users: Use only in dev/staging, delete or disable in production
  3. Role Permissions: Follow principle of least privilege
  4. Token Expiry: Default is 5 minutes (access) + 30 minutes (refresh)
  5. Audit Logs: Monitor authentication events in Admin Dashboard

For App Team (Them)

  1. Environment Variables: Never commit secrets to git
  2. HTTPS Only: Always use HTTPS in production
  3. Token Storage: Use httpOnly cookies (SDK handles this)
  4. RBAC Checks: Always check on backend, not just frontend
  5. Session Management: Implement proper logout

Quick Reference Commands

# Create new client ./scripts/create-oauth-client.sh # Create test users for client ./scripts/create-test-users.sh {client-id} # Get client secret ./scripts/get-client-secret.sh {client-id} # List all clients via API curl -X GET https://api.zewstid.com/v1/clients \ -H "Authorization: Bearer $ADMIN_TOKEN" # View client roles curl -X GET https://api.zewstid.com/v1/clients/{client-id}/roles \ -H "Authorization: Bearer $ADMIN_TOKEN" # Assign role to user curl -X POST https://api.zewstid.com/v1/users/{user-id}/roles \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "clientId": "{client-id}", "roles": ["{role-name}"] }'

Support & Resources


Example: Complete Zeye Onboarding

This is a real example showing exactly what was done for Zeye:

1. Admin Created Client

./scripts/create-oauth-client.sh # Input: # - Client ID: zeye-app # - Client Name: Zeye # - Root URL: https://zeye.zewst.com # - Redirect URIs: https://zeye.zewst.com/api/auth/callback/zewstid

2. Created Roles

  • zeye-admin
    - Full admin access
  • zeye-user
    - Camera management
  • zeye-viewer
    - Read-only

3. Created Test Users

  • zeye-admin@test.com
    /
    password
  • zeye-user@test.com
    /
    password
  • zeye-viewer@test.com
    /
    password

4. Shared with Zeye Team

ZEWSTID_ISSUER_URL=https://auth.zewstid.com/realms/zewstid ZEWSTID_CLIENT_ID=zeye-app ZEWSTID_CLIENT_SECRET=abc123...

Plus developer integration guide with code examples.

5. Zeye Team Integration

  • Installed
    @zewstid/nextjs@0.7.3
  • Configured authentication with ZewstID provider +
    enableSSOEstablishment: true
  • Implemented RBAC with role permissions
  • Protected routes with middleware
  • Added role checks in UI components

Result: Fully integrated authentication with cross-portal SSO in ~4 hours


Next Steps

For Track A (Internal Apps)

For Track B (External Apps)

Was this page helpful?

Let us know how we can improve our documentation