Skip to main content

Customizing the Authentication Experience

Learn how to customize the ZewstID authentication pages to match your application's branding and user experience.


Overview

ZewstID allows you to customize various aspects of the authentication experience for your users, including:

  • Brand Colors - Match your application's color scheme
  • Logos - Display your company logo
  • Custom Text - Modify messaging and labels
  • Email Templates - Customize authentication emails
  • Redirect Behavior - Control post-login flow

OAuth Client Branding

Configure via Admin Dashboard

  1. Go to https://admin.zewstid.com
  2. Navigate to Applications → Select your client
  3. Go to Branding tab
  4. Configure the following options:

Basic Branding:

{ "displayName": "My Application", "logoUrl": "https://myapp.com/logo.png", "primaryColor": "#6B46C1", "backgroundColor": "#FFFFFF" }

Advanced Options:

{ "termsOfServiceUrl": "https://myapp.com/terms", "privacyPolicyUrl": "https://myapp.com/privacy", "supportEmail": "support@myapp.com", "customCss": "https://myapp.com/auth-theme.css" }

Configure via API

curl -X PATCH https://api.zewstid.com/v1/clients/myapp \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "branding": { "displayName": "My Application", "logoUrl": "https://myapp.com/logo.png", "primaryColor": "#6B46C1", "backgroundColor": "#FFFFFF", "termsOfServiceUrl": "https://myapp.com/terms", "privacyPolicyUrl": "https://myapp.com/privacy" } }'

Email Template Customization

Configure Email Templates

Customize the emails sent during authentication flows (magic links, OTP, password reset, etc.):

import { ZewstID } from '@zewstid/nextjs'; const zewstid = new ZewstID({ clientId: process.env.ZEWSTID_CLIENT_ID!, apiKey: process.env.ZEWSTID_API_KEY! }); // Configure email templates await zewstid.emails.updateTemplate({ clientId: 'myapp', template: 'magic-link', subject: 'Sign in to {{app_name}}', body: ` <html> <body style="font-family: Arial, sans-serif;"> <div style="max-width: 600px; margin: 0 auto;"> <img src="{{logo_url}}" alt="{{app_name}}" style="width: 150px;"> <h1>Welcome back!</h1> <p>Click the button below to sign in to {{app_name}}:</p> <a href="{{magic_link_url}}" style="background: {{primary_color}}; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px;"> Sign In </a> <p style="color: #666; font-size: 12px;"> This link expires in {{expiry_minutes}} minutes. </p> </div> </body> </html> ` });

Available Templates:

  • magic-link
    - Magic link authentication
  • otp
    - One-time password codes
  • password-reset
    - Password reset emails
  • email-verification
    - Email verification
  • welcome
    - Welcome email for new users

Available Variables:

  • {{app_name}}
    - Your application name
  • {{logo_url}}
    - Your logo URL
  • {{primary_color}}
    - Your primary brand color
  • {{magic_link_url}}
    - Magic link URL (magic-link template only)
  • {{otp_code}}
    - OTP code (otp template only)
  • {{reset_url}}
    - Password reset URL (password-reset only)
  • {{expiry_minutes}}
    - Link/code expiry time

Custom Authentication Pages

Using the SDK Components

The ZewstID SDK provides pre-built, customizable components:

'use client'; import { LoginForm } from '@zewstid/nextjs/client'; export default function SignInPage() { return ( <div className="auth-container"> <LoginForm logo="/my-logo.svg" primaryColor="#6B46C1" showSocialProviders={['google', 'github']} customText={{ title: "Welcome to My App", subtitle: "Sign in to continue", submitButton: "Continue", forgotPassword: "Need help signing in?" }} onSuccess={(session) => { window.location.href = '/dashboard'; }} /> </div> ); }

Building Custom UI

For complete control, build your own authentication UI using the SDK's headless functions:

'use client'; import { useState } from 'react'; import { useMagicLink } from '@zewstid/nextjs/client'; export default function CustomLoginPage() { const [email, setEmail] = useState(''); const { sendMagicLink, isLoading, error } = useMagicLink(); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); await sendMagicLink({ email }); }; return ( <div className="my-custom-auth-page"> <img src="/my-logo.svg" alt="My App" /> <h1>Welcome to My App</h1> <form onSubmit={handleSubmit}> <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Enter your email" className="custom-input" /> <button type="submit" disabled={isLoading} className="custom-button" > {isLoading ? 'Sending...' : 'Continue with Email'} </button> </form> {error && <div className="error">{error.message}</div>} </div> ); }

Redirect Behavior

Custom Redirect URLs

Control where users land after authentication:

// In your authentication handler export async function GET(request: Request) { const { searchParams } = new URL(request.url); const returnTo = searchParams.get('returnTo') || '/dashboard'; const authUrl = zewstid.auth.buildAuthUrl({ redirectUri: `${process.env.NEXT_PUBLIC_APP_URL}/api/auth/callback`, state: encodeURIComponent(returnTo) }); return Response.redirect(authUrl); } // In your callback handler export async function GET(request: Request) { const { searchParams } = new URL(request.url); const code = searchParams.get('code'); const state = searchParams.get('state'); const session = await zewstid.auth.handleCallback({ code }); const returnTo = state ? decodeURIComponent(state) : '/dashboard'; return Response.redirect(returnTo); }

Conditional Redirects

Redirect based on user roles:

import { getServerSession } from '@zewstid/nextjs/server'; export async function GET() { const session = await getServerSession(); if (!session) { return Response.redirect('/auth/signin'); } // Redirect based on role if (session.user.roles.includes('admin')) { return Response.redirect('/admin/dashboard'); } else if (session.user.roles.includes('manager')) { return Response.redirect('/manager/dashboard'); } else { return Response.redirect('/dashboard'); } }

Localization

Multi-Language Support

Customize text for different locales:

const translations = { en: { title: "Welcome to My App", signIn: "Sign In", email: "Email address" }, es: { title: "Bienvenido a Mi Aplicación", signIn: "Iniciar sesión", email: "Correo electrónico" }, fr: { title: "Bienvenue sur Mon Application", signIn: "Se connecter", email: "Adresse e-mail" } }; export default function LocalizedLoginPage({ locale }: { locale: string }) { const t = translations[locale] || translations.en; return ( <LoginForm customText={{ title: t.title, submitButton: t.signIn, emailPlaceholder: t.email }} /> ); }

Advanced Customization

Custom CSS

Apply custom styles to authentication pages:

/* public/auth-theme.css */ :root { --auth-primary: #6B46C1; --auth-secondary: #9333EA; --auth-background: #F3F4F6; --auth-text: #1F2937; } .zewstid-auth-container { background: var(--auth-background); font-family: 'Your Custom Font', sans-serif; } .zewstid-button-primary { background: linear-gradient(135deg, var(--auth-primary), var(--auth-secondary)); border-radius: 8px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; } .zewstid-input { border: 2px solid var(--auth-primary); border-radius: 8px; font-size: 16px; } .zewstid-logo { filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.1)); }

Reference in your client configuration:

curl -X PATCH https://api.zewstid.com/v1/clients/myapp \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "branding": { "customCss": "https://myapp.com/auth-theme.css" } }'

Custom Domain

Use your own domain for authentication pages:

  1. Configure DNS CNAME record:

    auth.myapp.com CNAME id.zewstid.com
  2. Contact ZewstID support to configure SSL certificate

  3. Update your OAuth client configuration:

    curl -X PATCH https://api.zewstid.com/v1/clients/myapp \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "customDomain": "auth.myapp.com" }'

Best Practices

1. Brand Consistency

Ensure your authentication pages match your application:

  • ✅ Use the same logo, colors, and fonts
  • ✅ Match button styles and spacing
  • ✅ Use consistent terminology

2. User Experience

Keep authentication simple and familiar:

  • ✅ Minimize required fields
  • ✅ Provide clear error messages
  • ✅ Show loading states
  • ✅ Auto-focus on email input

3. Mobile Responsiveness

Test on mobile devices:

  • ✅ Use responsive design
  • ✅ Ensure touch targets are ≥44px
  • ✅ Test in portrait and landscape

4. Accessibility

Make authentication accessible to all users:

  • ✅ Use semantic HTML
  • ✅ Provide alt text for images
  • ✅ Ensure sufficient color contrast (WCAG AA)
  • ✅ Support keyboard navigation

5. Performance

Optimize for fast loading:

  • ✅ Use CDN for logos and CSS
  • ✅ Minimize custom CSS
  • ✅ Optimize image sizes
  • ✅ Test on slow connections

Examples

Minimal Branding

{ "displayName": "My App", "logoUrl": "https://myapp.com/logo.png", "primaryColor": "#2563EB" }

Full Branding

{ "displayName": "My Enterprise App", "logoUrl": "https://myapp.com/logo.svg", "faviconUrl": "https://myapp.com/favicon.ico", "primaryColor": "#6B46C1", "backgroundColor": "#FFFFFF", "textColor": "#1F2937", "termsOfServiceUrl": "https://myapp.com/terms", "privacyPolicyUrl": "https://myapp.com/privacy", "supportEmail": "support@myapp.com", "customCss": "https://myapp.com/auth-theme.css", "customDomain": "auth.myapp.com" }

Troubleshooting

Logo Not Displaying

Issue: Custom logo not showing on auth pages Solution:

  1. Ensure logo URL is publicly accessible
  2. Use HTTPS for logo URL
  3. Check image format (PNG, SVG, or JPG recommended)
  4. Verify image size is reasonable (< 200KB)

Custom CSS Not Applied

Issue: Custom styles not appearing Solution:

  1. Verify CSS URL is publicly accessible via HTTPS
  2. Check browser console for CORS errors
  3. Ensure CSS selectors match ZewstID's class names
  4. Clear browser cache and test in incognito mode

Colors Not Matching

Issue: Brand colors look different on auth pages Solution:

  1. Use hex color codes (e.g.,
    #6B46C1
    )
  2. Test in different browsers
  3. Check for color profile differences
  4. Ensure sufficient contrast for accessibility

Next Steps

Was this page helpful?

Let us know how we can improve our documentation