Introducing Socket Firewall: Free, Proactive Protection for Your Software Supply Chain.Learn More
Socket
Book a DemoInstallSign in
Socket

@wristband/typescript-jwt

Package Overview
Dependencies
Maintainers
3
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@wristband/typescript-jwt

A framework-agnostic Typescript SDK that validates JWT access tokens issued by Wristband for user or machine authentication.

latest
Source
npmnpm
Version
0.1.0
Version published
Maintainers
3
Created
Source
Github

Enterprise-ready auth that is secure by default, truly multi-tenant, and ungated for small businesses.

WebsiteDocumentation



Wristband JWT Validation SDK for Typescript

npm package version number Actions Status License

This framework-agnostic Typescript SDK validates JWT access tokens issued by Wristband for user or machine authentication. It uses the Wristband JWKS endpoint to resolve signing keys and verify RS256 signatures. Validation includes issuer verification, lifetime checks, and signature validation using cached keys. Developers should use this to protect routes and ensure that only valid, Wristband-issued access tokens can access secured APIs.

You can learn more about JWTs in Wristband in our documentation:


Requirements

This SDK is designed to work for any Typescript framework (Node.js 20+, Deno, Bun, Cloudflare Workers, etc.) and relies on native Web APIs.


1) Installation

npm install @wristband/typescript-jwt

or

yarn add @wristband/typescript-jwt

or

pnpm add @wristband/typescript-jwt

You should see the dependency added to your package.json file:

{
  "dependencies": {
    "@wristband/typescript-jwt": "^0.1.0"
  }
}

2) Wristband Configuration

First, you'll need to make sure you have an Application in your Wristband Dashboard account. If you haven't done so yet, refer to our docs on Creating an Application.

Make sure to copy the Application Vanity Domain for next steps, which can be found in "Application Settings" for your Wristband Application.


3) SDK Configuration

First, create an instance of WristbandJwtValidator in your server's directory structure in any location of your choice (i.e.: src/wristband.ts). Then, you can export this instance and use it across your project. When creating an instance, you provide all necessary configurations for your application to correlate with how you've set it up in Wristband.

// src/wristband.ts
// ESModules import:
import { createWristbandJwtValidator } from '@wristband/typescript-jwt';
// Or CommonJS import:
// const { createWristbandJwtValidator } = require('@wristband/typescript-jwt');

const wristbandJwtValidator = createWristbandJwtValidator({
  wristbandApplicationVanityDomain: 'auth.yourapp.io',
});

// ESModules export:
export { wristbandJwtValidator };
// Or CommonJS export:
// module.exports = { wristbandJwtValidator };

4) Extract and Validate JWT Tokens

The SDK provides methods to extract Bearer tokens from Authorization headers and validate them. Here are examples for a few frameworks:

Express

// middleware.ts
import { Request, Response, NextFunction } from 'express';
import { wristbandJwtValidator } from './wristband';

export const requireAuth = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const token = wristbandJwtValidator.extractBearerToken(req.headers.authorization);
    const result = await wristbandJwtValidator.validate(token);
    
    if (result.isValid) {
      req.user = result.payload;
      next();
    } else {
      res.status(401).json({ error: result.errorMessage });
    }
  } catch (error) {
    res.status(401).json({ error: 'Authentication required' });
  }
};


// server.ts
import express from 'express';
import { requireAuth } from './middleware';

const app = express();

// Apply to protected routes
app.get('/api/protected/data', requireAuth, (req, res) => {
  res.json({ message: 'Hello from protected API!', user: req.user });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

NextJS

// middleware.ts
import { NextRequest, NextResponse } from 'next/server';
import { wristbandJwtValidator } from './wristband';

export async function middleware(request: NextRequest) {
  try {
    const authHeader = request.headers.get('authorization');
    const token = wristbandJwtValidator.extractBearerToken(authHeader);
    const result = await wristbandJwtValidator.validate(token);
    
    if (!result.isValid) {
      return NextResponse.json(
        { error: result.errorMessage }, 
        { status: 401 }
      );
    }
    
    // Add user info to headers for downstream API routes
    const response = NextResponse.next();
    response.headers.set('x-user-id', result.payload?.sub || '');
    return response;
  } catch (error) {
    return NextResponse.json(
      { error: 'Authentication required' }, 
      { status: 401 }
    );
  }
}

export const config = {
  matcher: '/api/protected/:path*'
};

Deno

// middleware.ts
import { wristbandJwtValidator } from './wristband';

export async function requireAuth(req: Request, next: () => Promise<Response>): Promise<Response> {
  try {
    const authHeader = req.headers.get('Authorization');
    const token = wristbandJwtValidator.extractBearerToken(authHeader);
    const result = await wristbandJwtValidator.validate(token);
    
    if (!result.isValid) {
      return new Response(JSON.stringify({ error: result.errorMessage }), {
        status: 401,
        headers: { 'Content-Type': 'application/json' }
      });
    }
    
    // Add user to request context
    (req as any).user = result.payload;
    return await next();
  } catch (error) {
    return new Response(JSON.stringify({ error: 'Authentication required' }), {
      status: 401,
      headers: { 'Content-Type': 'application/json' }
    });
  }
}


// server.ts
import { requireAuth } from './auth.ts';

const protectedHandler = requireAuth(async (req, user) => {
  return new Response(JSON.stringify({ 
    message: 'Hello from protected API!',
    user 
  }), {
    headers: { 'Content-Type': 'application/json' }
  });
});

async function handler(req: Request): Promise<Response> {
  const url = new URL(req.url);
  
  if (url.pathname === '/api/protected') {
    return await protectedHandler(req);
  }
  
  return new Response('Not Found', { status: 404 });
}

Deno.serve({ port: 8000 }, handler);

JWKS Caching and Expiration

The SDK automatically retrieves and caches JSON Web Key Sets (JWKS) from your Wristband application's domain to validate incoming access tokens. By default, keys are cached in memory and reused across requests to avoid unnecessary network calls.

You can control how the SDK handles this caching behavior using two optional configuration values: jwksCacheMaxSize and jwksCacheTtl.

Set a limit on how many keys to keep in memory:

const validator = createWristbandJwtValidator({
  wristbandApplicationVanityDomain: 'auth.yourapp.io',
  jwksCacheMaxSize: 10 // Keep at most 10 keys in cache
});

Set a time-to-live duration for each key:

const validator = createWristbandJwtValidator({
  wristbandApplicationVanityDomain: 'auth.yourapp.io',
  jwksCacheTtl: 2629746000 // Expire keys from cache after 1 month (in milliseconds)
});

If jwksCacheTtl is not set, cached keys remain available until evicted by the cache size limit.


SDK Configuration Options

JWT Validation OptionTypeRequiredDescription
jwksCacheMaxSizenumberNoMaximum number of JWKs to cache in memory. When exceeded, the least recently used keys are evicted. Defaults to 20.
jwksCacheTtlnumberNoTime-to-live for cached JWKs, in milliseconds. If not set, keys remain in cache until eviction by size limit.
wristbandApplicationVanityDomainstringYesYes The Wristband vanity domain used to construct the JWKS endpoint URL for verifying tokens. Example: myapp.wristband.dev.

API Reference

createWristbandJwtValidator(config)

This is a factory function that creates a configured JWT validator instance.

Parameters:

NameTypeRequiredDescription
configWristbandJwtValidatorConfigYesConfiguration options (see SDK Configuration Options)

Returns:

  • The Configured WristbandJwtValidator instance

Example:

const validator = createWristbandJwtValidator({
  wristbandApplicationVanityDomain: 'myapp.wristband.dev',
  jwksCacheMaxSize: 20,
  jwksCacheTtl: 3600000
});

extractBearerToken(authorizationHeader)

This is used to extract the raw Bearer token from an HTTP Authorization header. It can handle various input formats and validates the Bearer scheme according to RFC 6750.

The function will throw an error for the following cases:

  • The Authorization header is missing
  • The Authorization header is malformed
  • The Authorization header contains multiple entries
  • The Authorization header uses wrong scheme (i.e. not using Bearer)
  • The Authorization header is missing the token value

Parameters:

NameTypeRequiredDescription
authorizationHeaderstring or string[]YesThe Authorization header value(s) of the current request.

Returns:

TypeDescription
stringThe extracted Bearer token

Valid usage examples:

const token1 = wristbandJwtValidator.extractBearerToken('Bearer abc123');
const token2 = wristbandJwtValidator.extractBearerToken(['Bearer abc123']);
// From Express.js request
const token3 = wristbandJwtValidator.extractBearerToken(req.headers.authorization);
// From Next.js request
const token4 = wristbandJwtValidator.extractBearerToken(request.headers.get('authorization'));

Invalid cases that throw errors:

wristbandJwtValidator.extractBearerToken(['Bearer abc', 'Bearer xyz']);
wristbandJwtValidator.extractBearerToken([]);
wristbandJwtValidator.extractBearerToken('Basic abc123');
wristbandJwtValidator.extractBearerToken('Bearer ');

validate(token)

Validates a JWT access token issued by Wristband. Performs comprehensive validation including format checking, signature verification, issuer validation, and expiration checks.

Parameters:

NameTypeRequiredDescription
tokenstringYesThe Wristband JWT token to validate.

Returns:

TypeDescription
Promise<JwtValidationResult>Validation result object.

JwtValidationResult interface:

interface JwtValidationResult {
  isValid: boolean;
  payload?: JWTPayload;     // Present when isValid is true
  errorMessage?: string;    // Present when isValid is false
}

JWTPayload interface:

interface JWTPayload {
  iss?: string;           // Issuer
  sub?: string;           // Subject (user ID)
  aud?: string | string[]; // Audience
  exp?: number;           // Expiration time (Unix timestamp)
  nbf?: number;           // Not before (Unix timestamp)
  iat?: number;           // Issued at (Unix timestamp)
  jti?: string;           // JWT ID
  [key: string]: any;     // Any additional Wristband/custom claims
}

Valid usage examples:

const result = await validator.validate(token);

if (result.isValid) {
  console.log('User ID:', result.payload?.sub);
  console.log('Expires at:', new Date(result.payload?.exp! * 1000));
} else {
  console.error('Validation failed:', result.errorMessage);
}

Questions

Reach out to the Wristband team at support@wristband.dev for any questions regarding this SDK.


Keywords

wristband

FAQs

Package last updated on 02 Jul 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts