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

signifyid-client

v1.2.6

Published

Official React SDK for Signify iD - Digital Identity & Access Management

Readme

signifyid-client

Official React SDK for Signify iD - Digital Identity & Access Management

npm version TypeScript License: MIT React Version

Overview

signifyid-client is a production-ready React SDK that provides seamless integration with Signify iD's authentication platform. It supports both CommonJS and ES Module builds with full TypeScript support, making it compatible with modern React applications, Next.js, and beyond.

Key Features

  • Single Sign-On (SSO) - Unified authentication across multiple applications
  • Session Management - Secure, token-based authentication with automatic refresh
  • Protected Routes - Built-in component for authentication-gated routes
  • Multi-Factor Authentication - Support for enhanced security options
  • TypeScript First - Complete type definitions included
  • Framework Agnostic - Works with React, Next.js (App & Pages Router), and standard React SPAs
  • SSR Safe - Proper handling of server-side rendering concerns
  • Zero External Dependencies - Minimal bundle size impact

Installation

Install the package using your preferred package manager:

npm install signifyid-client
yarn add signifyid-client
pnpm add signifyid-client

Prerequisites

  • React 17.0.0 or higher
  • React DOM 17.0.0 or higher

Quick Start

Step 1: Configure Environment Variables

Add the required configuration to your environment file:

# .env.local (Next.js) or .env
NEXT_PUBLIC_SIGNIFY_API_URL=https://signifyid-api.vercel.app
NEXT_PUBLIC_SIGNIFY_LOGIN_URL=https://signifyid.vercel.app/client/login

Step 2: Initialize the Provider

Wrap your application with SignifyProvider:

// app/layout.tsx (Next.js App Router)
import { SignifyProvider } from "signifyid-client";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html>
      <body>
        <SignifyProvider
          config={{
            apiUrl: process.env.NEXT_PUBLIC_SIGNIFY_API_URL!,
            loginUrl: process.env.NEXT_PUBLIC_SIGNIFY_LOGIN_URL!,
            env: "production", // 'production' or 'development'
          }}
        >
          {children}
        </SignifyProvider>
      </body>
    </html>
  );
}

Step 3: Protect Routes

Use ProtectedRoute to guard components requiring authentication:

// app/dashboard/page.tsx
import { ProtectedRoute } from "signifyid-client";
import Dashboard from "./Dashboard";

export default function DashboardPage() {
  return (
    <ProtectedRoute>
      <Dashboard />
    </ProtectedRoute>
  );
}

Step 4: Access Authentication State

Use the useSignifyAuth hook to interact with authentication:

"use client";

import { useSignifyAuth } from "signifyid-client";

export function Navbar() {
  const { isAuthenticated, isLoading, user, login, logout } = useSignifyAuth();

  if (isLoading) {
    return <nav>Loading authentication state...</nav>;
  }

  return (
    <nav>
      {isAuthenticated ? (
        <>
          <span>Welcome, {user?.name}</span>
          <button onClick={logout}>Sign Out</button>
        </>
      ) : (
        <button onClick={login}>Sign In with Signify iD</button>
      )}
    </nav>
  );
}

Core API

SignifyProvider

Root provider component that establishes the authentication context throughout your application.

Props:

  • config (required) - Configuration object with:
    • apiUrl (string) - Backend API endpoint URL
    • loginUrl (string) - Signify iD login page URL
    • cookieName? (string) - Session cookie name (default: "clientSession")
    • cookieMaxAge? (number) - Cookie expiration in seconds (default: 86400)
    • tokenParam? (string) - URL parameter for token extraction (default: "token")
    • debug? (boolean) - Enable debug logging (default: false)
    • env? (string) - Environment setting: "production" or "development". When set to "development", API calls and login redirects are disabled for security and cost-prevention (default: "development")
  • onAuthStateChange? - Callback function invoked on authentication state changes

Example:

<SignifyProvider
  config={{
    apiUrl: "https://signifyid-api.vercel.app",
    loginUrl: "https://signifyid.vercel.app/client/login",
    env: "production",
    debug: process.env.NODE_ENV === "development",
  }}
  onAuthStateChange={(state) => {
    if (state.isAuthenticated) {
      // Handle authenticated state
    }
  }}
>
  {children}
</SignifyProvider>

useSignifyAuth

Hook to access authentication state and methods within a SignifyProvider context.

Returns: | Property | Type | Description | |----------|------|-------------| | isAuthenticated | boolean | User authentication status | | isLoading | boolean | Session validation in progress | | session | SignifySession \| null | Complete session object | | user | SignifyUser \| null | Authenticated user data | | login() | () => void | Redirect to Signify iD login page | | logout() | () => Promise<void> | Clear session and sign out user | | validateSession() | () => Promise<void> | Manually validate session |

Example:

"use client";

import { useSignifyAuth } from "signifyid-client";

export function Profile() {
  const { user, isLoading, logout } = useSignifyAuth();

  if (isLoading) return <div>Loading...</div>;

  return (
    <div>
      <h1>{user?.name}</h1>
      <button onClick={logout}>Sign Out</button>
    </div>
  );
}

ProtectedRoute

Component that conditionally renders children only when user is authenticated.

Props:

  • children (required) - Component to render when authenticated
  • loadingComponent? - Loading UI displayed during session validation
  • redirectUrl? - Custom redirect URL (default: login URL)
  • onRedirect? - Callback before redirect to login

Example:

<ProtectedRoute loadingComponent={<LoadingSpinner />} redirectUrl="/auth/login">
  <Dashboard />
</ProtectedRoute>

useSignifyConfig

Hook to access resolved configuration values.

Returns: Configuration object containing all provider settings

const config = useSignifyConfig();
console.log(config.apiUrl);

Utility Functions

Exported utility functions for advanced use cases:

import {
  setCookie, // Set HTTP cookie
  getCookie, // Retrieve cookie value
  deleteCookie, // Remove cookie
  getTokenFromUrl, // Extract token from URL parameters
  cleanUrlParams, // Remove parameters from URL
  isBrowser, // Check if running in browser environment
} from "signifyid-client";

Authentication Flow

The SDK follows a redirect-based OAuth-style authentication pattern:

┌──────────────────┐        ┌─────────────────┐        ┌────────────────┐
│  Your App        │        │  Signify iD     │        │  Backend API   │
│                  │        │  Login Portal   │        │                │
└────────┬─────────┘        └────────┬────────┘        └────────┬───────┘
         │                          │                          │
         │  1. User accesses        │                          │
         │     protected route      │                          │
         │                          │                          │
         │  2. Redirect ───────────>│                          │
         │     ?redirect=app.com    │                          │
         │                          │                          │
         │                  3. User signs in                   │
         │                          │                          │
         │  4. Redirect <───────────│                          │
         │     ?token=JWT_TOKEN     │                          │
         │                          │                          │
         │  5. Extract & store token in secure cookie          │
         │                          │                          │
         │  6. Validate session ───────────────────────────────>│
         │                          │                          │
         │  7. Session data <──────────────────────────────────│
         │                          │                          │
         │  8. User authenticated ✓ │                          │

Integration Examples

Next.js App Router (13+)

Root Layout:

// app/layout.tsx
import { SignifyProvider } from "signifyid-client";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <SignifyProvider
          config={{
            apiUrl: process.env.NEXT_PUBLIC_SIGNIFY_API_URL!,
            loginUrl: process.env.NEXT_PUBLIC_SIGNIFY_LOGIN_URL!,
            env: "production",
            debug: process.env.NODE_ENV === "development",
          }}
        >
          {children}
        </SignifyProvider>
      </body>
    </html>
  );
}

Protected Layout:

// app/dashboard/layout.tsx
import { ProtectedRoute } from "signifyid-client";

export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <ProtectedRoute
      loadingComponent={
        <div className="flex items-center justify-center min-h-screen">
          <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500" />
        </div>
      }
    >
      {children}
    </ProtectedRoute>
  );
}

Next.js Pages Router

Application Entry:

// pages/_app.tsx
import type { AppProps } from "next/app";
import { SignifyProvider } from "signifyid-client";

export default function App({ Component, pageProps }: AppProps) {
  return (
    <SignifyProvider
      config={{
        apiUrl: process.env.NEXT_PUBLIC_SIGNIFY_API_URL!,
        loginUrl: process.env.NEXT_PUBLIC_SIGNIFY_LOGIN_URL!,
      }}
    >
      <Component {...pageProps} />
    </SignifyProvider>
  );
}

Protected Page:

// pages/dashboard.tsx
import { ProtectedRoute, useSignifyAuth } from "signifyid-client";

function DashboardContent() {
  const { user, logout } = useSignifyAuth();

  return (
    <div>
      <h1>Welcome, {user?.name}</h1>
      <p>Email: {user?.email}</p>
      <button onClick={logout}>Sign Out</button>
    </div>
  );
}

export default function DashboardPage() {
  return (
    <ProtectedRoute>
      <DashboardContent />
    </ProtectedRoute>
  );
}

Standard React SPA

// src/App.tsx
import {
  SignifyProvider,
  ProtectedRoute,
  useSignifyAuth,
} from "signifyid-client";

function Dashboard() {
  const { user, logout } = useSignifyAuth();
  return (
    <div>
      <h1>Welcome, {user?.name}</h1>
      <button onClick={logout}>Sign Out</button>
    </div>
  );
}

export function App() {
  return (
    <SignifyProvider
      config={{
        apiUrl: process.env.REACT_APP_SIGNIFY_API_URL!,
        loginUrl: process.env.REACT_APP_SIGNIFY_LOGIN_URL!,
        env: "production",
      }}
    >
      <ProtectedRoute>
        <Dashboard />
      </ProtectedRoute>
    </SignifyProvider>
  );
}

TypeScript Support

Full TypeScript support is included out of the box. The package exports comprehensive type definitions for all components and hooks.

Exported Types:

import type {
  SignifyConfig,
  SignifySession,
  SignifyUser,
  SignifyAuthState,
  SignifyProviderProps,
  ProtectedRouteProps,
} from "signifyid-client";

Type Safety Example:

interface ExtendedUser extends SignifyUser {
  organizationId: string;
  role: "admin" | "user" | "viewer";
}

export function AdminPanel() {
  const { user } = useSignifyAuth();
  const adminUser = user as ExtendedUser | null;

  if (adminUser?.role !== "admin") {
    return <div>Access Denied</div>;
  }

  return <div>Admin Content</div>;
}

Advanced Usage

Auth State Change Callbacks

Listen to authentication state changes at the provider level:

<SignifyProvider
  config={config}
  onAuthStateChange={(state) => {
    if (state.isAuthenticated && state.user) {
      // Track user authentication
      analytics.identify(state.user.id);
    } else {
      // Clear user-specific data
      analytics.reset();
    }
  }}
>
  {children}
</SignifyProvider>

Custom Redirect Behavior

<ProtectedRoute
  redirectUrl="/auth/login"
  onRedirect={() => {
    // Custom logic before redirect
    console.log("User will be redirected to login");
  }}
>
  <Dashboard />
</ProtectedRoute>

Manual Session Validation

Re-validate session on demand:

import { useSignifyAuth } from "signifyid-client";

export function AuthStatus() {
  const { validateSession, isAuthenticated } = useSignifyAuth();

  const handleRefresh = async () => {
    await validateSession();
  };

  return (
    <div>
      <p>Status: {isAuthenticated ? "Authenticated" : "Not authenticated"}</p>
      <button onClick={handleRefresh}>Refresh Session</button>
    </div>
  );
}

Advanced Cookie Configuration

<SignifyProvider
  config={{
    apiUrl: "https://signifyid-api.vercel.app",
    loginUrl: "https://signifyid.vercel.app/client/login",
    cookieName: "my_session_token",
    cookieMaxAge: 604800, // 7 days in seconds
    tokenParam: "auth_token", // Custom URL parameter name
    debug: true, // Enable verbose logging
  }}
>
  {children}
</SignifyProvider>

Security Considerations

The SDK implements security best practices throughout:

  • Server-Side Rendering Safe - All browser APIs are protected with isBrowser() checks
  • Cross-Domain Credentials - Uses credentials: 'include' for proper cookie handling
  • Automatic Token Cleanup - Token parameters are removed from URL after extraction
  • CSRF Protection - Cookies are set with SameSite=Lax
  • No Client-Side Token Storage - Authentication tokens are stored exclusively in secure HTTP-only cookies
  • Session Validation - Regular server-side session validation prevents token tampering

Troubleshooting

"useSignifyAuth must be used within a SignifyProvider"

Ensure your component is a child of <SignifyProvider>:

// ❌ Incorrect - Component outside provider
<SignifyProvider>...</SignifyProvider>
<MyComponent />

// ✅ Correct - Component inside provider
<SignifyProvider>
  <MyComponent />
</SignifyProvider>

Session Not Persisting After Redirect

Verify the following:

  1. apiUrl and loginUrl are correctly configured
  2. CORS is enabled on your backend server
  3. Cookies are being set (check DevTools → Application → Cookies)
  4. Session validation endpoint is accessible at POST /api/client-auth/session/validate

Infinite Redirect Loop

This typically indicates session validation is failing. Check:

  1. Backend service is running and accessible
  2. Session validation endpoint is properly configured
  3. Request credentials are being sent and processed correctly
  4. Server is returning valid session data in response

Debug Mode

Enable debug logging for troubleshooting:

<SignifyProvider
  config={{
    apiUrl: process.env.NEXT_PUBLIC_SIGNIFY_API_URL!,
    loginUrl: process.env.NEXT_PUBLIC_SIGNIFY_LOGIN_URL!,
    debug: true,
  }}
>
  {children}
</SignifyProvider>

Contributing

We welcome contributions to improve the SDK. Please review our contributing guidelines before submitting pull requests.

For bug reports or feature requests, please open an issue on our GitHub repository.


Publishing

This package is built with tsup and supports multiple output formats:

  • CommonJS: dist/index.cjs (for Node.js and bundlers)
  • ES Modules: dist/index.js (for modern browsers and build tools)
  • TypeScript Definitions: dist/index.d.ts and dist/index.d.cts

Build the package:

npm run build

Watch mode for development:

npm run dev

Type checking:

npm run typecheck

License

MIT License © Signify iD

See the LICENSE file for details.


Support

For questions, issues, or support:

  • 📧 Email: [email protected]
  • 🌐 Website: https://signifyid.vercel.app
  • 📚 Documentation: https://docs.signifyid.com