npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@carisls/sso-standard

v1.3.1

Published

A middleware implementing standard flow SSO

Readme

@carisls/sso-standard

A middleware implementing standard OIDC/OAuth2 authorization code flow SSO for Express.js applications. This package provides a complete, ready-to-use authentication solution with automatic token management, session handling, and user mapping.

Features

  • 🔐 Complete OIDC/OAuth2 authorization code flow implementation
  • 🍪 Automatic cookie-based session management with encryption
  • 🔄 Automatic token refresh handling
  • 👤 User token mapping and request injection
  • 🛡️ Built-in authorization middleware
  • 🌐 Multi-provider support (Keycloak, Okta, and other OIDC providers)
  • 🔑 JWKS-based public key validation with caching
  • 📦 Supports both ESM and CommonJS
  • 🎯 Customizable endpoints and paths
  • 🔒 Secure cookie handling with encryption

Installation

npm install @carisls/sso-standard

Quick Start

ESM (ECMAScript Modules)

import express from 'express';
import { router } from '@carisls/sso-standard';

const app = express();

app.use(router({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  // Simple format: comma-separated string
  providers: 'https://auth.example.com',
  // Or array format: providers: [{ ssoUrl: 'https://auth.example.com' }],
  encPassword: 'your-encryption-password'
}));

app.listen(3000);

CommonJS

const express = require('express');
const { router } = require('@carisls/sso-standard');

const app = express();

app.use(router({
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  // Simple format: comma-separated string
  providers: 'https://auth.example.com',
  // Or array format: providers: [{ ssoUrl: 'https://auth.example.com' }],
  encPassword: 'your-encryption-password'
}));

app.listen(3000);

API Reference

router(options)

Creates and configures an Express router with complete SSO authentication flow.

Parameters:

  • options (Object): Configuration object with the following properties:
    • clientId (string, required): SSO Client ID registered with your identity provider
    • clientSecret (string, required): SSO Client Secret
    • providers (string | Array, required): Provider configuration(s). Can be:
      • A comma-separated string of provider URLs (e.g., 'https://auth1.example.com,https://auth2.example.com')
      • An array of provider configuration objects:
        • ssoUrl (string): Base URL for the provider (usually equal to iss). Used to discover OpenID Connect configuration
        • iss (string, optional): Issuer identifier. If not provided, defaults to ssoUrl
        • publicKey (string, optional): Static public key in PEM format (if not using JWKS)
    • encPassword (string, required): Password used for encrypting cookies
    • encPasswordSalt (string, optional): Salt for password derivation (default: 'C5mp4Hl$X9wby#s5')
    • encIterationCount (number, optional): Iteration count for key derivation (default: 123123)
    • publicKeyCache (number, optional): Public key caching expiration in seconds (default: 300)
    • expOffset (number, optional): Force renewal of tokens earlier (in seconds) to handle clock skew issues (default: 0)
    • groups (boolean, optional): Request groups scope from the provider (default: true)
    • userMapper (function, optional): Custom function to map tokens to user object. Signature: (token, idToken) => userObject
    • paths (Object, optional): Customize default endpoint paths
      • login (string, default: '/login'): Login initiation endpoint
      • sso (string, default: '/sso'): SSO callback endpoint
      • afterLogin (string, default: '/'): Redirect after successful login
      • logout (string, default: '/logout'): Logout initiation endpoint
      • afterLogout (string, default: '/'): Redirect after successful logout

Returns: Express Router instance with the following endpoints configured:

  • GET /login (or custom path): Initiates SSO login flow
  • GET /sso (or custom path): Handles SSO callback and token exchange
  • GET /logout (or custom path): Initiates logout flow
  • Automatic token refresh middleware
  • User injection middleware (adds req.user to authenticated requests)

Example:

import express from 'express';
import { router } from '@carisls/sso-standard';

const app = express();

app.use(router({
  clientId: 'my-app-client',
  clientSecret: 'my-secret-key',
  // Simple format: comma-separated string
  providers: 'https://auth.example.com',
  // Or detailed format: array of objects
  // providers: [
  //   {
  //     ssoUrl: 'https://auth.example.com',
  //     // iss defaults to ssoUrl if not provided
  //   }
  // ],
  encPassword: 'my-encryption-password-123',
  publicKeyCache: 600,
  expOffset: 60,
  groups: true,
  paths: {
    login: '/auth/login',
    sso: '/auth/callback',
    afterLogin: '/dashboard',
    logout: '/auth/logout',
    afterLogout: '/'
  },
  userMapper: (token, idToken) => {
    return {
      id: token.sub,
      email: token.email,
      name: token.name,
      roles: token.roles || []
    };
  }
}));

// Protected route - user is automatically available via req.user
app.get('/dashboard', (req, res) => {
  res.json({
    message: 'Welcome!',
    user: req.user
  });
});

app.listen(3000);

authorize(role, exceptions, redirectToLogin)

Express.js middleware for authorization filtering based on user roles. This middleware works in conjunction with the router to provide role-based access control.

Parameters:

  • role (string | string[] | undefined, optional): Role(s) to filter by. If undefined, only checks for authenticated user.
  • exceptions (string[] | undefined, optional): Array of URL paths to skip authorization checks.
  • redirectToLogin (boolean, default: false): If true, redirects to login page instead of returning 401.

Returns: Express middleware function (req, res, next) => void

Example:

import express from 'express';
import { router, authorize } from '@carisls/sso-standard';

const app = express();

// Setup SSO router
app.use(router({
  clientId: 'my-client-id',
  clientSecret: 'my-secret',
  // Simple format: comma-separated string
  providers: 'https://auth.example.com',
  // Or array format: providers: [{ ssoUrl: 'https://auth.example.com' }],
  encPassword: 'encryption-password'
}));

// Require any authenticated user
app.use(authorize());

// Require specific role
app.get('/admin', authorize('admin'), (req, res) => {
  res.json({ message: 'Admin access granted', user: req.user });
});

// Require one of multiple roles
app.get('/dashboard', authorize(['admin', 'user']), (req, res) => {
  res.json({ message: 'Dashboard access', user: req.user });
});

// With exceptions and redirect
app.use(authorize('user', ['/public', '/health'], true));

app.listen(3000);

Complete Example

import express from 'express';
import { router, authorize } from '@carisls/sso-standard';

const app = express();

// Configure SSO middleware
app.use(router({
  clientId: process.env.SSO_CLIENT_ID,
  clientSecret: process.env.SSO_CLIENT_SECRET,
  // Simple format: comma-separated string (iss defaults to ssoUrl)
  providers: process.env.SSO_URL,
  // Or array format with custom iss:
  // providers: [
  //   {
  //     ssoUrl: process.env.SSO_URL,
  //     iss: process.env.SSO_ISSUER // optional, defaults to ssoUrl
  //   }
  // ],
  encPassword: process.env.ENCRYPTION_PASSWORD,
  publicKeyCache: 600,
  paths: {
    login: '/login',
    sso: '/sso',
    afterLogin: '/dashboard',
    logout: '/logout',
    afterLogout: '/'
  }
}));

// Public routes
app.get('/', (req, res) => {
  res.send('Welcome! <a href="/login">Login</a>');
});

// Protected routes - require authentication
app.get('/dashboard', authorize(), (req, res) => {
  res.json({
    message: 'Dashboard',
    user: req.user
  });
});

// Admin routes - require admin role
app.get('/admin', authorize('admin'), (req, res) => {
  res.json({
    message: 'Admin panel',
    user: req.user
  });
});

// API routes with role-based access
app.get('/api/users', authorize(['admin', 'user-manager']), (req, res) => {
  res.json({ users: [] });
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

How It Works

  1. Login Flow: When a user visits /login, they are redirected to the identity provider's authorization endpoint with the appropriate OAuth2 parameters.

  2. Callback Handling: After authentication, the provider redirects back to /sso with an authorization code. The middleware exchanges this code for access, refresh, and ID tokens.

  3. Token Storage: Tokens are encrypted and stored in HTTP-only cookies:

    • x-session: Encrypted access token
    • x-session-sso: Encrypted refresh token
    • x-session-id: Encrypted ID token (used for logout)
  4. User Injection: On each request, the middleware decrypts tokens, validates them, and injects a req.user object containing user information.

  5. Token Refresh: The middleware automatically refreshes access tokens when they expire using the stored refresh token.

  6. Logout: Visiting /logout clears all cookies and redirects to the identity provider's logout endpoint.

Supported Providers

This package works with any OIDC-compliant identity provider, including:

  • Keycloak
  • Okta
  • Auth0
  • Azure AD
  • Google Identity Platform
  • Any other OIDC/OAuth2 provider

User Object Structure

By default, the req.user object follows this structure (can be customized with userMapper):

{
  iss: string;              // Issuer
  id: string;               // User ID (from 'sub')
  sid?: string;             // Session ID
  sa: boolean;              // Service account flag
  azp?: string;             // Authorized party
  name?: {                  // Name object (if available)
    full: string;
    familyName: string;
    givenName: string;
  };
  email?: string;           // Email (if available)
  roles: string[];          // User roles
}

Environment Variables

For production use, store sensitive values in environment variables:

SSO_CLIENT_ID=your-client-id
SSO_CLIENT_SECRET=your-client-secret
SSO_URL=https://auth.example.com
SSO_ISSUER=https://auth.example.com
ENCRYPTION_PASSWORD=your-strong-encryption-password

Security Considerations

  • Cookie Encryption: All tokens are encrypted before being stored in cookies
  • HTTP-Only Cookies: Prevents XSS attacks by making cookies inaccessible to JavaScript
  • Secure Cookies: Automatically enabled when using HTTPS
  • Token Validation: All tokens are validated using JWKS before use
  • Automatic Refresh: Tokens are refreshed before expiration to prevent service interruption

Dependencies

  • @carisls/sso-core: Core SSO utilities (token validation, encryption, etc.)
  • express: Web framework
  • cookie-parser: Cookie parsing middleware
  • debug: Debug logging utility

License

MIT

Author

Mihovil Strujic [email protected]