A CAS client built for Next.js to authenticate, validate tickets, and provide session management to a CAS server
npm install next-cas-client_Maintained by the University of Hawaiʻi._
Designed for Next.js, next-cas-client serves as an API platform to interact with a CAS server to authenticate, validate tickets, and provide session management (powered by iron-session).
Currently supports CAS 2.0, CAS 3.0 and SAML 1.1 service validation methods.
Contributions to this repo to support more validation protocols is highly encouraged! (See contributing)
- Getting Started
- Installation
- Set Environment Variables
- Add API Route
- Usage
- login(): void
- logout(): void
- getCurrentUser
- isLoggedIn(): Promise
- Examples
- Contributing
- FAQ
- Is there support for other React frameworks like Vite and Remix?
- How do I use getCurrentUser() and isLoggedIn() in a client component?
- How do I resolve the error when importing getCurrentUser() and isLoggedIn() from 'next-cas-client/app' or 'next-cas-client/pages'?
``bashUsing npm:
npm i next-cas-client
$3
.env:`
NEXT_PUBLIC_BASE_URL=https://example.com
NEXT_PUBLIC_CAS_URL=https://cas.example.com/cas
NEXT_CAS_CLIENT_SAML_TOLERANCE=18000
`-
NEXT_PUBLIC_BASE_URL (Required): The URL to redirect to after logging-in/out
- NEXT_PUBLIC_CAS_URL (Required): The URL prefix of your CAS server
- NEXT_CAS_CLIENT_SAML_TOLERANCE _(Optional)_: The tolerance in milliseconds for drifting clocks when validating SAML tickets. Only applies to SAML 1.1 validation. Defaults to 1000 milliseconds..env.local:`
NEXT_CAS_CLIENT_SECRET=GenerateA32CharacterLongPassword
`-
NEXT_CAS_CLIENT_SECRET (Required): The secret used to encrypt/decrypt the session stored as a cookie. It must be greater than 32 characters long. Use https://1password.com/password-generator to generate a password.$3
App Router:
app/api/cas/[client]/route.ts:`ts
import { ValidatorProtocol } from 'next-cas-client';
import { handleAuth } from 'next-cas-client/app';export const GET = handleAuth({ validator: ValidatorProtocol.CAS30 });
`Page Router:
pages/api/cas/[client].ts:`ts
import { ValidatorProtocol } from 'next-cas-client';
import { handleAuth } from 'next-cas-client/pages';export default handleAuth({ validator: ValidatorProtocol.CAS30 });
`handleAuth() Options:
-
validator (Required): The ValidatorProtocol enum
- ValidatorProtocol.CAS20 for CAS 2.0 service validation
- ValidatorProtocol.CAS20 for CAS 3.0 service validation
- ValidatorProtocol.SAML11 for SAML 1.1 validation
- loadUser _(Optional)_: Function to redefine the user object stored in session. - Parameters:
casUser: CasUser
- Returns: any | Promise
- If a loadUser function is not passed in, the stored user in session defaults to a object of type CasUser:
`ts
type CasUser = {
user: string;
attributes: record;
};
`
- Example: Using loadUser to redefine the user and store authorization roles:
`ts
import { handleAuth, ValidatorProtocol } from 'next-cas-client'; async function loadUser(casUser: CasUser) {
const user = {
uid: casUser.user
name: casUser.attributes.name,
email: casUser.attributes.email,
roles: []
}
await setRoles(user); // Makes API call(s) to retrieve and set the user's roles
return user;
}
export default handleAuth({ loadUser, validator: ValidatorProtocol.SAML11 });
`Usage
$3
Visits the CAS login page.
`jsx
'use client';import { login } from 'next-cas-client';
;
`login() Options:
-
renew _(Optional)_: Boolean, true to disallow SSO. Defaults to false.$3
Visits the CAS logout page.
`jsx
'use client';import { login } from 'next-cas-client';
;
`logout() Options:
-
enableSLO _(Optional)_: Boolean, true to enable SLO (Single Logout). Destroys current SSO session. Defaults to false.$3
Gets the current user. Returns
null if no user is logged-in.App Router:
`ts
import { getCurrentUser } from 'next-cas-client/app';const currentUser = await getCurrentUser();
`Page Router:
`ts
import { getCurrentUser } from 'next-cas-client/pages';export const getServerSideProps = (async (context) => {
return { props: { currentUser: await getCurrentUser(context) } };
}) satisfies GetServerSideProps<{ currentUser: CasUser | null }>;
`Returns an object of type
CasUser by default. Define the generic type of getCurrentUser() if you used the loadUser option in handleAuth(). The type should match the return of the loadUser function you defined.- Example:
`ts
type User = {
uid: string;
name: string;
email: string;
roles: string[];
}; const currentUser = await getCurrentUser();
`$3
Returns
true if a user is logged-in.App Router:
`ts
import { getCurrentUser } from 'next-cas-client/app';const isLoggedIn = await isLoggedIn();
`Page Router:
`ts
import { getCurrentUser } from 'next-cas-client/pages';export const getServerSideProps = (async (context) => {
return { props: { isLoggedIn: await isLoggedIn(context) } };
}) satisfies GetServerSideProps<{ isLoggedIn: boolean }>;
`Examples
A fully functional demo is available using Docker.
To start:
1. Clone or download this repo
2. Change directory to
/examples
3. Execute docker compose up. A CAS server for demo purposes will launch at https://localhost:8443/cas
4. Change directory to /app-router or /pages-router depending on the router you would like to view the example for
5. Execute npm install then npm run dev. The Next.js example app will be available at http://localhost:3000Note: You may encounter a
NET:ERR_CERT_INVALID error in your browser when attempting to visit the CAS login page. Bypass the error by trusting the page. The browser is attempting to protect you from visiting a suspicious secure site at https://localhost.Contributing
Please open a new issue before creating a PR. This project is currently focusing on supporting more ticket validation protocols. Any other issues and PRs created out of this scope may be rejected.
For more information on how to contribute, view here.
FAQ
$3
No, not at this moment.
$3
It is recommended to use those functions inside a server component then pass them as props into a client component.
$3
In your project's
tsconfig.json, set compilerOptions.moduleResolution` to "bundler".