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 🙏

© 2024 – Pkg Stats / Ryan Hefner

next-cas-client

v1.3.2

Published

A CAS client built for Next.js to authenticate, validate tickets, and provide session management to a CAS server

Downloads

335

Readme

next-cas-client CI Coverage GitHub license

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)

Table of Contents

Getting Started

1. Installation

# Using npm:
npm i next-cas-client

# Using pnpm:
pnpm add next-cas-client

# Using yarn:
yarn add next-cas-client

2. Set Environment Variables

.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. Add API Route

App Router: app/api/cas/[client]/route.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:

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<any>

    • If a loadUser function is not passed in, the stored user in session defaults to a object of type CasUser:

      type CasUser = {
          user: string;
          attributes: record<string, string | string[]>;
      };
    • Example: Using loadUser to redefine the user and store authorization roles:

      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

login(): void (Client-Side Only)

Visits the CAS login page.

'use client';

import { login } from 'next-cas-client';

<button onClick={() => login()}>Login</button>;

login() Options:

  • renew (Optional): Boolean, true to disallow SSO. Defaults to false.

logout(): void (Client-Side Only)

Visits the CAS logout page.

'use client';

import { login } from 'next-cas-client';

<button onClick={() => logout()}>Logout</button>;

logout() Options:

  • enableSLO (Optional): Boolean, true to enable SLO (Single Logout). Destroys current SSO session. Defaults to false.

getCurrentUser<T>(): Promise<T = CasUser | null> (Server-Side Only)

Gets the current user. Returns null if no user is logged-in.

App Router:

import { getCurrentUser } from 'next-cas-client/app';

const currentUser = await getCurrentUser();

Page Router:

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:

    type User = {
        uid: string;
        name: string;
        email: string;
        roles: string[];
    };
    
    const currentUser = await getCurrentUser<User>();

isLoggedIn(): Promise<boolean> (Server-Side Only)

Returns true if a user is logged-in.

App Router:

import { getCurrentUser } from 'next-cas-client/app';

const isLoggedIn = await isLoggedIn();

Page Router:

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:3000

Note: 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

Is there support for other React frameworks like Vite and Remix?

No, not at this moment.

How do I use getCurrentUser() and isLoggedIn() in a client component?

It is recommended to use those functions inside a server component then pass them as props into a client component.

How do I resolve the error when importing getCurrentUser() and isLoggedIn() from 'next-cas-client/app' or 'next-cas-client/pages'?

In your project's tsconfig.json, set compilerOptions.moduleResolution to "bundler".