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

@usu-accessibility/auth-service-handler

v1.0.25

Published

A modern TypeScript package for handling authentication services.

Downloads

681

Readme

@usu-accessibility/auth-service-handler

A modern TypeScript package for handling authentication services across servers (Hono/Fetch) and clients (React).

  • Handles persisting sessions via HTTP-only cookies.
  • Provides helpers to read the current session in server code.
  • Exposes a simple way to construct a login URL (with optional redirect support).
  • Includes React hooks to read the session and logout from the browser.
  • Server helpers to fetch users and roles; create, update, and delete roles; and create, update, or delete users.

Installation

npm install @usu-accessibility/auth-service-handler

Configuration

You can configure the library via environment variables or by passing options to createAuthHandler().

Required values:

  • AUTH_APP_ID
  • AUTH_APP_SECRET
  • AUTH_ON_SUCCESS_REDIRECT_URL
  • AUTH_ON_ERROR_REDIRECT_URL
  • AUTH_SERVER_URL

You may also pass these as options directly to createAuthHandler(options); any option provided will override the corresponding environment variable.

API Reference

createAuthHandler(options?)

Creates an auth helper bound to your app configuration.

Signature: createAuthHandler(options?: { appId?, appSecret?, onSuccessRedirectUrl?, onErrorRedirectUrl?, authServerUrl? })

Returns:

  • getServerSession(headers: Headers) => Promise<Session | null> — Server helper to read and validate the current session from the incoming request headers.
  • getLoginData(options?: { redirectUrl?: string }) => { url: string } — Returns the login URL to start the SAML flow. Optionally appends a redirectUrl query param to control post-login redirection.
  • getUsers(opts: { aNumbers?: string[]; roles?: string[] }) => Promise<Session["user"][]> — Fetches user profiles filtered by A-numbers and/or roles using your auth server.
  • getRoles() => Promise<Role[]> — Fetches all available roles from your auth server.
  • createRole(name: string) => Promise<Role> — Creates a new role on your auth server.
  • createUser(params: { aNumber: string; name?: string; email?: string; roleId?: string }) => Promise<Session["user"] & { createdAt: string; updatedAt: string; isInitialized: boolean }> — Creates a new user on your auth server.
  • deleteUser(aNumber: string) => Promise<true> — Deletes a user (by A-number) on your auth server.
  • updateUserRole(aNumber: string, roleId: string) => Promise<true> — Updates a user's role on your auth server.
  • deleteRole(roleId: string) => Promise<true> — Deletes a role on your auth server.
  • updateRole(roleId: string, name: string) => Promise<true> — Renames/updates a role on your auth server.
  • options: AuthOptions — The resolved configuration used by this handler.

Example:

import { createAuthHandler } from "@usu-accessibility/auth-service-handler";

const auth = createAuthHandler({
  appId: process.env.AUTH_APP_ID,
  appSecret: process.env.AUTH_APP_SECRET,
  onSuccessRedirectUrl: process.env.AUTH_ON_SUCCESS_REDIRECT_URL,
  onErrorRedirectUrl: process.env.AUTH_ON_ERROR_REDIRECT_URL,
  authServerUrl: process.env.AUTH_SERVER_URL,
});

// Server-side session
const session = await auth.getServerSession(request.headers);

// Create login URL
const { url: loginUrl } = auth.getLoginData({
  redirectUrl: "https://your.app/after-login",
});

Server Handlers

The library provides two platform-focused handlers you can mount on your server. Each handler expects to be mounted on a base route (e.g., /auth) and uses the last path segment to switch behavior:

  • POST/GET /auth/set?session=...&redirectUrl=... — Sets the session cookie and redirects to redirectUrl if provided, otherwise to AUTH_ON_SUCCESS_REDIRECT_URL.
  • GET /auth/session — Returns the current Session as JSON when authenticated. On missing/invalid session: Fetch handler responds 401; Hono handler responds 200 with null.
  • POST /auth/logout — Logs the user out, deletes the cookie, and redirects to /.
  • GET /auth/login-url?redirectUrl=/path — Returns { url: string } JSON for initiating login. The redirectUrl is appended only if it starts with /.

Exports and imports:

  • Fetch-compatible handler: import { fetchHandler } from "@usu-accessibility/auth-service-handler/handlers/fetch"
  • Hono handler: import { honoHandler } from "@usu-accessibility/auth-service-handler/handlers/hono"

Both handlers are factories: call them with your resolved AuthOptions to get a request handler.

Hono example

import { Hono } from "hono";
import { createAuthHandler } from "@usu-accessibility/auth-service-handler";
import { honoHandler } from "@usu-accessibility/auth-service-handler/handlers/hono";

const app = new Hono();
const auth = createAuthHandler();

// Mount once and let the handler switch by path suffix
app.get("/auth/*", honoHandler(auth.options));
app.post("/auth/*", honoHandler(auth.options));

// Usage examples:
// - GET  /auth/session  -> returns JSON session
// - POST /auth/logout   -> logs out and redirects
// - GET  /auth/set?session=token&redirectUrl=https://your.app/after
// - GET  /auth/login-url?redirectUrl=/after -> returns JSON { url }

Fetch (standard Web Request/Response) example

This works in environments with the standard Fetch API (e.g., Cloudflare Workers, Next.js Route Handlers, Bun, Deno, or Node 18+ with Fetch).

import { createAuthHandler } from "@usu-accessibility/auth-service-handler";
import { fetchHandler } from "@usu-accessibility/auth-service-handler/handlers/fetch";

const auth = createAuthHandler();
const handleAuth = fetchHandler(auth.options);

export async function GET(req: Request) {
  // Mount at /auth/* and forward requests here
  return handleAuth(req);
}

export async function POST(req: Request) {
  return handleAuth(req);
}

// Examples once mounted under /auth/*:
// GET  /auth/session
// POST /auth/logout
// GET  /auth/set?session=token&redirectUrl=https://your.app/after
// GET  /auth/login-url?redirectUrl=/after

Note: If you’re using Express without a Fetch-compatible adapter, you’ll need a small shim to convert Express’s req/res to Request/Response. Many community adapters exist; otherwise consider Hono which runs on Node and many other runtimes.

Server Helpers

getServerSession(authOptions)

Signature: (headers: Headers) => Promise<Session | null>

Reads the Cookie header, extracts the session token, validates it against your auth server, and returns a Session object or null.

Usage via createAuthHandler():

const auth = createAuthHandler();
const session = await auth.getServerSession(request.headers);
if (!session) {
  // handle unauthorized
}

getLoginData(authOptions)

Signature: (options?: { redirectUrl?: string }) => { url: string }

Returns the login URL for starting the SAML auth flow. If you provide redirectUrl, it will be appended as a query parameter so your app can redirect the user post-login.

Usage via createAuthHandler():

const auth = createAuthHandler();
const { url: loginUrl } = auth.getLoginData({
  redirectUrl: "/after_login",
});
// Redirect the user to loginUrl

getUsers(authOptions)

Signature: (opts: { aNumbers?: string[]; roles?: string[] }) => Promise<Session["user"][]>

Fetches users from the auth server. Provide one or both filters:

  • aNumbers — Array of A-numbers to include
  • roles — Array of role names to include

Usage via createAuthHandler():

const auth = createAuthHandler();
const users = await auth.getUsers({
  aNumbers: ["A12345678"],
  roles: ["admin"],
});

Returns: Promise<Session["user"][]>

getRoles(authOptions)

Signature: () => Promise<Role[]>

Fetches all roles from the auth server.

Usage via createAuthHandler():

const auth = createAuthHandler();
const roles = await auth.getRoles();

createRole(authOptions)

Signature: (name: string) => Promise<Role>

Creates a new role on the auth server.

Usage via createAuthHandler():

const auth = createAuthHandler();
const role = await auth.createRole("editor");

createUser(authOptions)

Signature: (params: { aNumber: string; name?: string; email?: string; roleId?: string }) => Promise<Session["user"] & { createdAt: string; updatedAt: string; isInitialized: boolean }>

Creates a new user on the auth server.

Usage via createAuthHandler():

const auth = createAuthHandler();
const user = await auth.createUser({
  aNumber: "A12345678",
  name: "Ada Lovelace",
  email: "[email protected]",
  roleId: "role-id-123",
});

deleteUser(authOptions)

Signature: (aNumber: string) => Promise<true>

Deletes a user (by A-number) from the auth server.

Usage via createAuthHandler():

const auth = createAuthHandler();
await auth.deleteUser("A12345678");

updateUserRole(authOptions)

Signature: (aNumber: string, roleId: string) => Promise<true>

Updates a user's role on the auth server.

Usage via createAuthHandler():

const auth = createAuthHandler();
await auth.updateUserRole("A12345678", "role-id-123");

deleteRole(authOptions)

Signature: (roleId: string) => Promise<true>

Deletes a role from the auth server.

Usage via createAuthHandler():

const auth = createAuthHandler();
await auth.deleteRole("role-id-123");

updateRole(authOptions)

Signature: (roleId: string, name: string) => Promise<true>

Renames/updates a role on the auth server.

Usage via createAuthHandler():

const auth = createAuthHandler();
await auth.updateRole("role-id-123", "Content Editor");

React Hooks

Import from the React subpath:

import {
  useSession,
  useLogout,
  useLoginUrl,
} from "@usu-accessibility/auth-service-handler/react";

Common options:

  • { authUrl?: string } — Override the base auth URL used by the hooks. Defaults to /api/auth (internal AUTH_URL). When using the provided handlers, set this to your mounted base (e.g., /auth).

useSession(options?)

Signature: useSession(options?: { authUrl?: string })

Returns a union state of:

  • { session: Session; loading: false; error: null } when authenticated
  • { session: null; loading: false; error: null } when unauthenticated
  • { session: null; loading: true; error: null } while loading
  • { session: null; loading: false; error: string } on error

Example:

function Profile() {
  const state = useSession({ authUrl: "/auth" });

  if (state.loading) return <p>Loading...</p>;
  if (state.error) return <p>Error: {state.error}</p>;
  if (!state.session) return <a href="/login">Login</a>;

  return (
    <div>Hello, {state.session.user.name ?? state.session.user.aNumber}</div>
  );
}

Note: By default, the hook fetches from ${authUrl}/session (so pass the base, e.g., /auth).

When using the Fetch handler, unauthenticated requests return HTTP 401, so useSession will produce the error state. With the Hono handler, unauthenticated requests return 200 with null, so useSession will yield the unauthenticated state instead of an error.

useLogout(options?)

Signature: useLogout(options?: { authUrl?: string })

Returns { logout: () => Promise<{ success: true }>} . The logout function posts to ${authUrl}/logout and throws on non-OK responses.

Example:

function LogoutButton() {
  const { logout } = useLogout({ authUrl: "/auth" });

  return (
    <button
      onClick={async () => {
        await logout();
        window.location.href = "/";
      }}
    >
      Logout
    </button>
  );
}

useLoginUrl(options?)

Signature: useLoginUrl(options?: { authUrl?: string; redirectUrl?: string })

Returns { getLoginUrl: () => Promise<{ url: string }>} . The getLoginUrl function requests ${authUrl}/login-url and returns the constructed login URL. If redirectUrl is provided and starts with /, it will be included in the request.

Example:

function LoginLink() {
  const { getLoginUrl } = useLoginUrl({
    authUrl: "/auth",
    redirectUrl: "/after",
  });

  return (
    <button
      onClick={async () => {
        const { url } = await getLoginUrl();
        window.location.href = url;
      }}
    >
      Login
    </button>
  );
}

Types

// Available via: import type { AuthOptions, Session, Role } from "@usu-accessibility/auth-service-handler"
export type AuthOptions = {
  appId: string;
  appSecret: string;
  onSuccessRedirectUrl: string;
  onErrorRedirectUrl: string;
  authServerUrl: string;
};

export type Session = {
  id: string;
  user: {
    aNumber: string;
    name: string | null;
    email: string | null;
    avatarUrl: string;
    role: {
      id: string;
      name: string;
    };
  };
};

export type Role = {
  id: string;
  name: string;
  createdAt: string;
  updatedAt: string;
};

End-to-End Flow Summary

  1. Your app constructs a login URL via auth.getLoginData({ redirectUrl }) and redirects the user to it.
  2. After authentication, your auth server redirects back to your app’s /auth/set?session=...&redirectUrl=... endpoint.
  3. The handler sets a secure cookie and redirects to the provided redirectUrl (or the configured onSuccessRedirectUrl).
  4. Your app can now fetch /auth/session (server or client) to retrieve the current user Session.
  5. To sign out, POST /auth/logout and then redirect the user as desired.

Development

  • Source: src/
  • Build: dist/

License

ISC