signifyid/client
Official React SDK for Signify iD - Digital Identity & Access Management. Authenticate users in your React or Next.js app with Signify iD in under 5 minutes.
What is Signify iD?
Signify iD is a modern Digital Identity & Access Management platform that provides:
- Single Sign-On (SSO) - One login for all your applications
- Session Management - Secure, token-based authentication
- User Management - Comprehensive user administration
- Multi-Factor Authentication - Enhanced security options
This SDK enables seamless integration with Signify iD's redirect-based authentication flow.
Installation
npm install signifyid/clientyarn add signifyid/clientpnpm add signifyid/clientQuick Start (5 minutes)
1. Wrap your app with SignifyProvider
1 // app/layout.tsx (Next.js App Router) 2 import { SignifyProvider } from "signifyid/client"; 3 4 export default function RootLayout({ children }) { 5 return ( 6 <html> 7 <body> 8 <SignifyProvider 9 config={{ 10 apiUrl: process.env.NEXT_PUBLIC_SIGNIFY_API_URL!, 11 loginUrl: process.env.NEXT_PUBLIC_SIGNIFY_LOGIN_URL!, 12 }} 13 > 14 {children} 15 </SignifyProvider> 16 </body> 17 </html> 18 ); 19 }
2. Protect routes that require authentication
1 // app/dashboard/page.tsx 2 import { ProtectedRoute } from "signifyid/client"; 3 import Dashboard from "./Dashboard"; 4 5 export default function DashboardPage() { 6 return ( 7 <ProtectedRoute> 8 <Dashboard /> 9 </ProtectedRoute> 10 ); 11 }
3. Use the auth hook in your components
1 // components/Navbar.tsx 2 "use client"; 3 4 import { useSignifyAuth } from "signifyid/client"; 5 6 export function Navbar() { 7 const { isAuthenticated, isLoading, user, login, logout } = useSignifyAuth(); 8 9 if (isLoading) { 10 return <nav>Loading...</nav>; 11 } 12 13 return ( 14 <nav> 15 {isAuthenticated ? ( 16 <> 17 <span>Welcome, {user?.name}!</span> 18 <button onClick={logout}>Logout</button> 19 </> 20 ) : ( 21 <button onClick={login}>Login with Signify iD</button> 22 )} 23 </nav> 24 ); 25 }
4. Set up environment variables
# .env.local
NEXT_PUBLIC_SIGNIFY_API_URL=https://api.signifyid.com
NEXT_PUBLIC_SIGNIFY_LOGIN_URL=https://signifyid.com/client/loginThat's it! π
Your app now supports Signify iD authentication.
API Reference
SignifyProvider
The root provider that enables Signify iD authentication throughout your app.
<SignifyProvider
config={{
apiUrl: string; // Required: Backend API URL
loginUrl: string; // Required: Signify iD login page URL
cookieName?: string; // Optional: Cookie name (default: "clientSession")
cookieMaxAge?: number; // Optional: Cookie max age in seconds (default: 86400)
tokenParam?: string; // Optional: URL token parameter (default: "token")
debug?: boolean; // Optional: Enable debug logging (default: false)
}}
onAuthStateChange?: (state) => void // Optional: Callback on auth state changes
>
{children}
</SignifyProvider>Config Options
| Option | Type | Required | Description |
|---|---|---|---|
| apiUrl | string | Yes | Backend API URL for session validation |
| loginUrl | string | Yes | Signify iD login page URL |
| cookieName | string | No | Cookie name (default: "clientSession") |
| cookieMaxAge | number | No | Cookie max age in seconds (default: 86400) |
| tokenParam | string | No | URL token parameter name (default: "token") |
| debug | boolean | No | Enable debug logging (default: false) |
useSignifyAuth
Hook to access authentication state and methods.
const {
isAuthenticated, // boolean: Whether user is authenticated
isLoading, // boolean: Whether auth is being validated
session, // SignifySession | null: Full session data
user, // SignifyUser | null: User data (shortcut for session.user)
login, // () => void: Redirect to Signify iD login
logout, // () => Promise<void>: Log out and clear session
validateSession, // () => Promise<void>: Manually re-validate session
} = useSignifyAuth();Return Values
| Property | Type | Description |
|---|---|---|
| isAuthenticated | boolean | Whether user is authenticated |
| isLoading | boolean | Whether auth is being validated |
| session | SignifySession | null | Full session data |
| user | SignifyUser | null | User data (shortcut for session.user) |
| login | () => void | Redirect to Signify iD login |
| logout | () => Promise<void> | Log out and clear session |
| validateSession | () => Promise<void> | Manually re-validate session |
ProtectedRoute
Component that protects children by requiring authentication.
<ProtectedRoute
loadingComponent?: React.ReactNode // Optional: Custom loading UI
redirectUrl?: string // Optional: Custom redirect URL
onRedirect?: () => void // Optional: Callback before redirect
>
{children}
</ProtectedRoute>Props
| Prop | Type | Description |
|---|---|---|
| loadingComponent | React.ReactNode | Custom loading UI to show during auth check |
| redirectUrl | string | Custom URL to redirect unauthenticated users |
| onRedirect | () => void | Callback before redirect happens |
useSignifyConfig
Hook to access the resolved configuration.
const config = useSignifyConfig();
// Returns: { apiUrl, loginUrl, cookieName, cookieMaxAge, tokenParam, debug }Authentication Flow
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β Your App β β Signify iD β β Signify API β
β β β Login Page β β β
ββββββββββ¬βββββββββ ββββββββββ¬βββββββββ ββββββββββ¬βββββββββ
β β β
β 1. User visits β β
β protected route β β
β β β
β 2. Redirect ββββββββΊ β β
β ?redirect=... β β
β β β
β β 3. User logs in β
β β β
β 4. Redirect back βββ β β
β ?token=... β β
β β β
β 5. SDK extracts token, stores in cookie β
β β β
β 6. Validate session ββββββββββββββββββββββΊ β
β β β
β 7. Session data ββββββββββββββββββββββββββ β
β β β
β 8. User authenticatedβ β
β β β βNext.js Examples
App Router (Next.js 13+)
1 // app/layout.tsx 2 import { SignifyProvider } from "signifyid/client"; 3 4 export default function RootLayout({ 5 children, 6 }: { 7 children: React.ReactNode; 8 }) { 9 return ( 10 <html lang="en"> 11 <body> 12 <SignifyProvider 13 config={{ 14 apiUrl: process.env.NEXT_PUBLIC_SIGNIFY_API_URL!, 15 loginUrl: process.env.NEXT_PUBLIC_SIGNIFY_LOGIN_URL!, 16 debug: process.env.NODE_ENV === "development", 17 }} 18 > 19 {children} 20 </SignifyProvider> 21 </body> 22 </html> 23 ); 24 }
1 // app/dashboard/layout.tsx 2 import { ProtectedRoute } from "signifyid/client"; 3 4 export default function DashboardLayout({ 5 children, 6 }: { 7 children: React.ReactNode; 8 }) { 9 return ( 10 <ProtectedRoute 11 loadingComponent={ 12 <div className="flex items-center justify-center min-h-screen"> 13 <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500" /> 14 </div> 15 } 16 > 17 {children} 18 </ProtectedRoute> 19 ); 20 }
Pages Router
1 // pages/_app.tsx 2 import type { AppProps } from "next/app"; 3 import { SignifyProvider } from "signifyid/client"; 4 5 export default function App({ Component, pageProps }: AppProps) { 6 return ( 7 <SignifyProvider 8 config={{ 9 apiUrl: process.env.NEXT_PUBLIC_SIGNIFY_API_URL!, 10 loginUrl: process.env.NEXT_PUBLIC_SIGNIFY_LOGIN_URL!, 11 }} 12 > 13 <Component {...pageProps} /> 14 </SignifyProvider> 15 ); 16 }
1 // pages/dashboard.tsx 2 import { ProtectedRoute, useSignifyAuth } from "signifyid/client"; 3 4 function DashboardContent() { 5 const { user, logout } = useSignifyAuth(); 6 7 return ( 8 <div> 9 <h1>Welcome, {user?.name}!</h1> 10 <p>Email: {user?.email}</p> 11 <button onClick={logout}>Logout</button> 12 </div> 13 ); 14 } 15 16 export default function DashboardPage() { 17 return ( 18 <ProtectedRoute> 19 <DashboardContent /> 20 </ProtectedRoute> 21 ); 22 }
TypeScript Support
This package is written in TypeScript and includes full type definitions.
import type {
SignifyConfig,
SignifySession,
SignifyUser,
SignifyAuthState,
SignifyProviderProps,
ProtectedRouteProps,
} from "signifyid/client";Custom User Type
If your Signify iD returns additional user properties:
interface MyUser extends SignifyUser {
organizationId: string;
role: "admin" | "user";
}
const { user } = useSignifyAuth();
const myUser = user as MyUser | null;Advanced Usage
Listen to Auth State Changes
1 <SignifyProvider 2 config={config} 3 onAuthStateChange={(state) => { 4 if (state.isAuthenticated) { 5 analytics.identify(state.user?.id); 6 } 7 }} 8 > 9 {children} 10 </SignifyProvider>
Custom Redirect URL
<ProtectedRoute redirectUrl="/custom-login">
<Dashboard />
</ProtectedRoute>Manual Session Validation
const { validateSession } = useSignifyAuth();
// Re-validate session on demand
await validateSession();Utility Functions
For advanced use cases, utility functions are also exported:
import {
setCookie,
getCookie,
deleteCookie,
getTokenFromUrl,
cleanUrlParams,
isBrowser,
} from "signifyid/client";Security Considerations
- SSR Safe: All browser APIs are wrapped with
isBrowser()checks - Credentials: Uses
credentials: 'include'for cross-domain cookie support - Token Cleanup: Automatically removes token from URL after extraction
- Secure Cookies: Uses
SameSite=Laxfor CSRF protection - No Token Exposure: Tokens are stored in cookies, not in JavaScript state
Troubleshooting
"useSignifyAuth must be used within a SignifyProvider"
Make sure your component is a child of <SignifyProvider>:
// β Wrong
<SignifyProvider>...</SignifyProvider>
<MyComponent /> // Outside provider!
// β
Correct
<SignifyProvider>
<MyComponent /> // Inside provider
</SignifyProvider>Session not persisting after redirect
- Ensure your
apiUrlandloginUrlare correct - Check if CORS is configured on your backend
- Verify cookies are being set (check browser DevTools β Application β Cookies)
Infinite redirect loop
This usually happens when session validation always returns valid: false. Check:
- Your backend is running and accessible
- The session validation endpoint is correct:
POST /api/client-auth/session/validate - Credentials are being sent with the request
Contributing
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
License
MIT Β© Signify iD