Node.js CAS Client Middleware
http-cas-client provides a comprehensive Central Authentication Service (CAS) client middleware for Node.js environments, supporting CAS 1.0, 2.0+, and 3.0+ protocols. As of version 0.4.3, it offers core features like Single Sign-On (SSO), CAS Proxy capabilities (including proxy chain checking), and Single Logout (SLO). The library is designed to be framework-agnostic, providing direct integration with Node's native `http` module and specific wrappers for popular frameworks like Koa2, with support for both session-based and no-session modes. While actively maintained, the package is still in a pre-1.0 state, indicating potential for further evolution before a stable API is declared. Key differentiators include its explicit support for various CAS protocol versions and its flexibility in integration patterns, including cluster-friendliness (though this feature is marked 'TODO' in the README) and principal adaptation for debugging.
Common errors
-
TypeError: handler is not a function
cause Attempting to `require('http-cas-client/wrap/koa2')` and then use it directly as a function for native `http` server.fixEnsure you are importing the correct module: `const httpCasClient = require('http-cas-client');` for native HTTP, or `const koaCasClient = require('http-cas-client/wrap/koa2');` for Koa. -
Error: Ticket validation failed: Invalid ticket or service URL mismatch.
cause The `casServerUrlPrefix` or `serverName` configuration is incorrect, preventing the CAS server from validating the service ticket.fixDouble-check that `casServerUrlPrefix` points to the correct base URL of your CAS server and `serverName` is the exact, publicly accessible URL of your Node.js application. -
ReferenceError: Koa is not defined
cause Using `koaCasClient` or `koaSessionCasClient` wrappers without having Koa installed or imported.fixInstall Koa (`npm install koa`) and ensure it's imported at the top of your file (`const Koa = require('koa');` or `import Koa from 'koa';`).
Warnings
- gotcha When using the Koa2 wrapper, placing `koa-bodyparser` middleware *after* `http-cas-client` can prevent `bodyparser` from receiving `req.socket` data, leading to parsing issues.
- gotcha The library primarily uses CommonJS `require` syntax in its examples. While it ships TypeScript types, direct ESM `import` might require careful configuration or a build step in some Node.js environments.
- gotcha The `serverName` option must accurately reflect the base URL (protocol, host, and port) where your Node.js application is accessible. Misconfiguration will lead to incorrect CAS service URLs and failed authentication redirects.
- gotcha The library is in a pre-1.0 version (0.4.3). While seemingly stable, minor versions may introduce breaking changes without a major version increment, as per typical pre-1.0 SemVer practices.
Install
-
npm install http-cas-client -
yarn add http-cas-client -
pnpm add http-cas-client
Imports
- httpCasClient
const httpCasClient = require('http-cas-client');import httpCasClient from 'http-cas-client';
- koaCasClient
const koaCasClient = require('http-cas-client'); // Incorrect path const koaCasClient = require('http-cas-client/wrap/koa2');import koaCasClient from 'http-cas-client/wrap/koa2';
- koaSessionCasClient
const koaSessionCasClient = require('http-cas-client'); // Incorrect path const koaSessionCasClient = require('http-cas-client/wrap/koa2-session');import koaSessionCasClient from 'http-cas-client/wrap/koa2-session';
- Principal
import type { Principal } from 'http-cas-client';
Quickstart
import http from 'http';
import httpCasClient from 'http-cas-client';
const casServerUrlPrefix = process.env.CAS_SERVER_URL_PREFIX || 'http://localhost:9000/cas';
const serverName = process.env.APP_SERVER_NAME || 'http://127.0.0.1';
const handler = httpCasClient({
casServerUrlPrefix: casServerUrlPrefix,
serverName: serverName,
// Example of setting a custom logger
logger: console
});
http.createServer(async (req, res) => {
if (!await handler(req, res)) {
// If the handler returns false, it means a redirect or other action was taken,
// and the response has already been handled. Stop further processing.
return res.end();
}
// The principal and ticket are attached to the request object after successful authentication.
const { principal, ticket } = req;
console.log('Authenticated Principal:', principal);
console.log('CAS Ticket:', ticket);
// Your application logic for authenticated users
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`<h1>Hello, ${principal?.user || 'Guest'}!</h1><p>Attributes: ${JSON.stringify(principal?.attributes)}</p><p><a href="${casServerUrlPrefix}/logout">Logout</a></p>`);
}).listen(80,
() => console.log(`Application listening on port 80. CAS Server: ${casServerUrlPrefix}`)
);