CAS Plugin for Better Auth
The `better-auth-cas` package, currently at version `0.1.8`, is an early-stage plugin designed to integrate Central Authentication Service (CAS) functionality into the `better-auth` authentication framework. It provides standard CAS sign-in and callback endpoints, handles CAS ticket validation via `serviceValidate`, and includes robust profile mapping capabilities to translate CAS user attributes into `better-auth` user and session data. A key feature is the optional `onProfileResolved` hook, enabling custom persistence logic. It emphasizes solutions for common CAS integration challenges, such as managing CAS's separate SSO session cookies to prevent "auto-login" after a local logout and addressing `service` URL allowlist mismatches in CAS deployments. While in a pre-1.0 state, implying potential API changes, its initial release (v0.1.0 on 2026-03-19) indicates active development and a focused approach to providing a ready-to-use CAS solution for `better-auth` applications, shipping with TypeScript types for better developer experience.
Common errors
-
CAS Login Failed: Service URL Mismatch
cause The `service` parameter in the CAS login request does not match an allowlisted URL on the CAS server, or the `redirectUri` configured in the plugin is incorrect.fixEnsure the `redirectUri` option in `createStandardCasPlugin` is set to the exact, absolute URL of your CAS callback endpoint (e.g., `http://localhost:3000/api/auth/cas/callback`) and that this URL is allowlisted on your CAS server. -
User appears logged in after local signOut()
cause The CAS SSO session cookie remains active even after a local `better-auth` session is cleared, leading to immediate re-authentication via CAS if the user attempts to log in again.fixImplement a comprehensive logout strategy that clears both the local `better-auth` session and redirects the user to the CAS server's logout endpoint. Refer to the 'Recommended global logout' example in the README.
Warnings
- gotcha Users may appear to 'auto-login' immediately after a local logout from your application because CAS maintains its own separate SSO session cookie. Clearing only the local session will not invalidate the CAS session.
- gotcha Many CAS deployments require the `service` URL (the callback URL provided during login) to be explicitly allowlisted. A mismatch between the URL generated by the plugin and the allowlisted URL will result in CAS rejecting the authentication attempt.
- breaking As this package is in a pre-1.0 release (0.1.x), the API and configuration options are subject to change without adhering to strict semantic versioning. While stable for initial use, be prepared for potential API adjustments in minor or patch releases.
Install
-
npm install better-auth-cas -
yarn add better-auth-cas -
pnpm add better-auth-cas
Imports
- createStandardCasPlugin
const createStandardCasPlugin = require('better-auth-cas').createStandardCasPlugin;import { createStandardCasPlugin } from 'better-auth-cas'; - auth
import { auth } from '@/lib/auth'; - NextRequest, NextResponse
import { NextRequest, NextResponse } from 'next/server';
Quickstart
import { betterAuth } from 'better-auth';
import { createStandardCasPlugin } from 'better-auth-cas';
// In a production environment, casBaseUrl should come from environment variables.
const casBaseUrl = process.env.CAS_BASE_URL || 'https://cas.example.com/cas';
const callbackPath = process.env.CAS_CALLBACK_PATH || '/api/auth/cas/callback';
const providerId = process.env.CAS_PROVIDER_ID || 'cas';
export const auth = betterAuth({
emailAndPassword: {
enabled: true,
},
plugins: [
createStandardCasPlugin({
casBaseUrl: casBaseUrl,
callbackPath: callbackPath,
providerId: providerId,
// Optional: Set redirectUri if your CAS server requires an exact match for the service URL
// redirectUri: process.env.CAS_REDIRECT_URI || 'http://localhost:3000/api/auth/cas/callback',
// Optional: Custom profile mapping if CAS attributes differ from defaults
// profileMapping: {
// stableId: ['sAMAccountName', 'uid'],
// name: ['displayName'],
// email: ['mail'],
// image: ['thumbnailPhoto']
// }
}),
],
});