Skip to main content

@zewstid/node

Official ZewstID SDK for Node.js - Authentication for backend applications.

npm version License: Proprietary

✨ Features

Authentication & Authorization (v0.1.0)

  • JWT Validation - Fast and secure token verification
  • 🔐 JWKS Caching - Automatic key rotation with intelligent caching
  • 🛡️ Role-Based Access Control - Built-in RBAC middleware
  • 🔑 Token Introspection - Validate and introspect access tokens
  • High Performance - Optimized for production workloads
  • 🎯 TypeScript - Full type safety out of the box

Framework Integration

  • 📦 Express Middleware - Ready-to-use authentication middleware
  • Fastify Plugin - Native Fastify support
  • 🔧 Standalone Client - Use in any Node.js environment
  • 🎨 Flexible - Works with Koa, Hapi, or vanilla Node.js

Developer Experience

  • Minimal Dependencies - Uses only
    jose
    for JWT handling
  • 🐛 Debug Mode - Detailed logging for troubleshooting
  • 📖 Comprehensive Docs - Clear examples and API reference
  • 🔄 Auto Key Rotation - JWKS keys cached with auto-refresh

🚀 Installation

From ZewstID npm Registry:

npm install @zewstid/node --registry https://npm.zewstid.com/

Or configure registry in

.npmrc
:

# .npmrc @zewstid:registry=https://npm.zewstid.com/

Then install normally:

npm install @zewstid/node

Quick Start

Standalone Usage

import { ZewstID } from '@zewstid/node'; const zewstid = new ZewstID({ issuerUrl: 'https://auth.zewstid.com/realms/zewstid', clientId: 'your_client_id', }); // Validate a JWT token const user = await zewstid.getUser(token); console.log(user);

Express Middleware

import express from 'express'; import { requireAuth } from '@zewstid/node/express'; const app = express(); // Protected route app.get('/api/protected', requireAuth({ issuerUrl: 'https://auth.zewstid.com/realms/zewstid', clientId: process.env.ZEWSTID_CLIENT_ID, }), (req, res) => { res.json({ message: `Hello ${req.user?.name}`, user: req.user, }); } ); app.listen(3000);

API Reference

ZewstID
Class

Main client for token validation and user management.

Constructor:

const zewstid = new ZewstID({ issuerUrl?: string; // Default: https://auth.zewstid.com/realms/zewstid clientId?: string; // Your client ID clientSecret?: string; // For confidential operations audience?: string; // Expected JWT audience jwksCacheDuration?: number; // JWKS cache in seconds (default: 3600) debug?: boolean; // Enable debug logging });

Methods:

validateToken(token, options?)

Validate a JWT access token.

const payload = await zewstid.validateToken(token, { audience: 'my-api', issuer: 'https://auth.zewstid.com/realms/zewstid', maxAge: 3600, // Maximum token age in seconds });

getUser(token)

Validate token and get user information.

const user = await zewstid.getUser(token); // Returns: { id, name, email, roles, ... }

getUserInfo(accessToken)

Get user info from the

/userinfo
endpoint.

const user = await zewstid.getUserInfo(accessToken);

introspectToken(token)

Introspect a token (requires client credentials).

const result = await zewstid.introspectToken(token); // Returns: { active: true, scope: '...', ... }

revokeToken(token)

Revoke a token (requires client credentials).

await zewstid.revokeToken(token);

getOpenIDConfiguration()

Get OpenID configuration.

const config = await zewstid.getOpenIDConfiguration();

Express Middleware

requireAuth(options)

Require authentication for a route.

import { requireAuth } from '@zewstid/node/express'; app.get('/protected', requireAuth({ issuerUrl: 'https://auth.zewstid.com/realms/zewstid', clientId: 'your_client_id', debug: true, }), (req, res) => { // req.user is available // req.token contains the access token res.json({ user: req.user }); } );

Options:

interface ZewstIDMiddlewareOptions { // All ZewstID config options plus: getToken?: (req: Request) => string | null; // Custom token extractor onError?: (error: Error, req: Request, res: Response) => void; // Custom error handler }

optionalAuth(options)

Optional authentication (doesn't block if no token).

app.get('/public', optionalAuth({ clientId: 'your_client_id' }), (req, res) => { if (req.user) { res.json({ message: `Hello ${req.user.name}` }); } else { res.json({ message: 'Hello anonymous' }); } } );

requireRole(role, options?)

Require specific role(s).

import { requireAuth, requireRole } from '@zewstid/node/express'; app.get('/admin', requireAuth({ clientId: 'your_client_id' }), requireRole('admin'), // Single role (req, res) => { res.json({ message: 'Admin access' }); } ); // Multiple roles (user needs at least one) app.get('/moderator', requireAuth({ clientId: 'your_client_id' }), requireRole(['admin', 'moderator']), (req, res) => { res.json({ message: 'Moderator access' }); } );

requireAllRoles(roles, options?)

Require all specified roles.

import { requireAuth, requireAllRoles } from '@zewstid/node/express'; app.get('/super-admin', requireAuth({ clientId: 'your_client_id' }), requireAllRoles(['admin', 'verified']), (req, res) => { res.json({ message: 'Super admin access' }); } );

Advanced Usage

Custom Token Extraction

By default, tokens are extracted from the

Authorization: Bearer <token>
header. You can customize this:

requireAuth({ clientId: 'your_client_id', getToken: (req) => { // Extract from cookie return req.cookies.access_token; // Or from query parameter // return req.query.token as string; // Or from custom header // return req.headers['x-api-key'] as string; }, })

Custom Error Handling

requireAuth({ clientId: 'your_client_id', onError: (error, req, res) => { console.error('Auth error:', error); res.status(401).json({ error: 'Custom error message', details: error.message, }); }, })

Validate Token Without Middleware

import { ZewstID } from '@zewstid/node'; const zewstid = new ZewstID({ clientId: 'your_client_id', }); async function checkAuth(req, res, next) { const token = req.headers.authorization?.split(' ')[1]; if (!token) { return res.status(401).json({ error: 'No token' }); } try { const user = await zewstid.getUser(token); req.user = user; next(); } catch (error) { res.status(401).json({ error: 'Invalid token' }); } }

Role-Based Authorization

function checkRole(role: string) { return (req, res, next) => { if (!req.user) { return res.status(401).json({ error: 'Not authenticated' }); } if (!req.user.roles?.includes(role)) { return res.status(403).json({ error: 'Forbidden', message: `Required role: ${role}`, }); } next(); }; } app.get('/admin', requireAuth({ clientId: 'your_client_id' }), checkRole('admin'), (req, res) => { res.json({ message: 'Admin only' }); } );

Token Introspection

const zewstid = new ZewstID({ clientId: 'your_client_id', clientSecret: 'your_client_secret', }); const result = await zewstid.introspectToken(token); if (result.active) { console.log('Token is valid'); console.log('Scope:', result.scope); console.log('Expires:', new Date(result.exp! * 1000)); } else { console.log('Token is invalid or expired'); }

TypeScript

Full TypeScript support included.

import type { ZewstIDConfig, ZewstIDUser, ZewstIDTokenPayload, ValidateTokenOptions, } from '@zewstid/node'; // Express Request is automatically extended import { Request } from 'express'; function handler(req: Request) { // req.user is typed as ZewstIDUser | undefined // req.token is typed as string | undefined const user: ZewstIDUser | undefined = req.user; }

Environment Variables

ZEWSTID_CLIENT_ID=your_client_id_here ZEWSTID_CLIENT_SECRET=your_client_secret_here ZEWSTID_ISSUER_URL=https://auth.zewstid.com/realms/zewstid

Complete Express Example

import express from 'express'; import { requireAuth, requireRole, optionalAuth } from '@zewstid/node/express'; const app = express(); // Configuration const authConfig = { issuerUrl: process.env.ZEWSTID_ISSUER_URL, clientId: process.env.ZEWSTID_CLIENT_ID!, debug: process.env.NODE_ENV === 'development', }; // Public route app.get('/public', (req, res) => { res.json({ message: 'Public access' }); }); // Optional auth (personalized if authenticated) app.get('/welcome', optionalAuth(authConfig), (req, res) => { if (req.user) { res.json({ message: `Welcome back, ${req.user.name}!` }); } else { res.json({ message: 'Welcome, visitor!' }); } } ); // Protected route app.get('/profile', requireAuth(authConfig), (req, res) => { res.json({ user: req.user, token: req.token, }); } ); // Admin only app.get('/admin', requireAuth(authConfig), requireRole('admin'), (req, res) => { res.json({ message: 'Admin dashboard' }); } ); // Multiple roles (OR logic) app.get('/moderator', requireAuth(authConfig), requireRole(['admin', 'moderator']), (req, res) => { res.json({ message: 'Moderator tools' }); } ); // API endpoint with token validation app.post('/api/data', requireAuth(authConfig), async (req, res) => { // req.user is available // req.token contains the access token // Your business logic here res.json({ success: true, userId: req.user?.id, }); } ); // Error handling app.use((err, req, res, next) => { console.error(err); res.status(500).json({ error: 'Internal server error' }); }); app.listen(3000, () => { console.log('Server running on http://localhost:3000'); });

Fastify Example

Works with Fastify too:

import Fastify from 'fastify'; import { ZewstID } from '@zewstid/node'; const fastify = Fastify(); const zewstid = new ZewstID({ clientId: process.env.ZEWSTID_CLIENT_ID!, }); // Decorator for authentication fastify.decorateRequest('user', null); // Auth hook fastify.addHook('onRequest', async (request, reply) => { const authHeader = request.headers.authorization; if (!authHeader) { return reply.code(401).send({ error: 'No token' }); } const token = authHeader.split(' ')[1]; try { request.user = await zewstid.getUser(token); } catch (error) { return reply.code(401).send({ error: 'Invalid token' }); } }); fastify.get('/protected', async (request, reply) => { return { user: request.user }; }); fastify.listen({ port: 3000 });

Examples

FAQ

Q: How do I get the access token from my frontend? A: Your frontend SDK (@zewstid/react, @zewstid/nextjs) will send it in the

Authorization: Bearer <token>
header.

Q: Do I need client secret? A: Only for token introspection and revocation. JWT validation works without it.

Q: How often are JWKS keys refreshed? A: Keys are cached for 1 hour by default. Configure with

jwksCacheDuration
.

Q: Can I use this without Express? A: Yes! Use the

ZewstID
class directly for any Node.js application.

Support

License

Proprietary and Confidential

Copyright © 2025 Zewst, Inc. All Rights Reserved.

This software is proprietary and confidential. Unauthorized distribution or use is prohibited.

Was this page helpful?

Let us know how we can improve our documentation