Socket
Book a DemoInstallSign in
Socket

@wristband/react-client-auth

Package Overview
Dependencies
Maintainers
3
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@wristband/react-client-auth

A lightweight React SDK that pairs with your backend server auth to initialize and sync frontend sessions via secure session cookies.

2.0.0
latest
Source
npmnpm
Version published
Maintainers
3
Created
Source
Github

Enterprise-ready auth that is secure by default, truly multi-tenant, and ungated for small businesses.

WebsiteDocumentation



Wristband Client-Side Authentication SDK for React

npm package version number Actions Status License

The SDK handles authentication interactions in your app’s React frontend. It’s designed to work in tandem with your backend server that integrates with Wristband using the Backend Server Integration Pattern. The backend exposes a required Session Endpoint that the React SDK calls to initialize the app in the browser with an authenticated user session. The backend can also optionally expose a Token Endpoint, allowing the React SDK to retrieve access tokens and store them in its client-side cache for direct use in browser-based requests.

Migrating From Older SDK Versions

On an older version of our SDK? Check out our migration guide:


Installation

npm install @wristband/react-client-auth

or

yarn add @wristband/react-client-auth

Usage

[!NOTE] Important: Before using this SDK, you must have already implemented the required backend server endpoints for authentication in your server: Login, Logout, and Session. This SDK connects to those existing endpoints but does not implement them for you. Optionally, if you plan to use access tokens directly from the browser, then your backend server will also need to implement the Token Endpoint.

1) Use the Wristband Auth Provider

The WristbandAuthProvider establishes and manages authentication state throughout your application. This component fetches the user's session data from your backend server and makes it available via React Context.

The provider requires two URL endpoints:

  • loginUrl: The URL of your backend server's Login Endpoint that initiates the authentication process.
  • sessionUrl: The URL of your backend server's Session Endpoint that returns the current user's session data.

Place the WristbandAuthProvider at your app's root to ensure the user's authenticated state is available throughout your application and verified on initial load.

import { WristbandAuthProvider } from '@wristband/react-client-auth';

function App() {
  return (
    <WristbandAuthProvider
      loginUrl="https://your-server.com/api/auth/login"
      sessionUrl="https://your-server.com/api/v1/session"
    >
      <YourAppComponents />
    </WristbandAuthProvider>
  );
}

When working with TypeScript, you can provide type definitions for your session metadata to ensure proper type safety when working with that data in your application.

import { WristbandAuthProvider } from '@wristband/react-client-auth';

interface MySessionMetadata {
  displayName: string;
  email: string;
  roles: string[];
}

function AppRoot() {
  return (
    <WristbandAuthProvider<MySessionMetadata>
      loginUrl='/api/auth/login'
      sessionUrl='/api/v1/session'
    >
      <App />
    </WristbandAuthProvider>
  );
}

2) Use Auth and Session Hooks

The SDK provides two hooks for accessing authentication data:

useWristbandAuth()

This hook provides authentication status information and functionality:

  • isAuthenticated: Boolean indicating if the user has an authenticated session.
  • isLoading: Boolean indicating if the authentication status is still being determined.
  • authError: WristbandError object containing error details when authentication fails, or null when no error has occurred.
  • authStatus: Enum value for convenience (LOADING, AUTHENTICATED, or UNAUTHENTICATED).
  • clearAuthData(): Function that destroys all auth, session, and token data (auth status becomes UNAUTHENTICATED).

Use this hook when you need to control access to protected content by checking authentication status. This enables common patterns like conditional rendering of authenticated/unauthenticated views, route protection, or dynamic UI updates based on the user's auth status.

import { useWristbandAuth } from '@wristband/react-client-auth';

function AuthStatus() {
  const { authError, isAuthenticated, isLoading, authStatus, clearAuthData } = useWristbandAuth();
  
  if (isLoading) {
    return <div>Checking authentication status...</div>;
  }
  
  return (
    <div>
      <h2>Authentication Status: {authStatus}</h2>
      {isAuthenticated && (
        <button onClick={() => alert(`I'm authenticated!!`)}>
          Show Auth
        </button>
      )}
      {authError && (
        <>
          <p>Error code: {authError.code}</p>
          <p>Error message: {authError.message}</p>
        </>
      )}
    </div>
  );
}

The clearAuthData() function permanently clears all client-side auth state, session data, and token data. You can optionally use this when you need to completely reset the SDK state, typically for testing, error recovery, or when implementing custom logout flows. Note that this only clears React state and does not invalidate session cookies nor redirect the user. For standard logout, redirect to your server's Logout Endpoint instead.

import { redirectToLogin, useWristbandAuth } from '@wristband/react-client-auth';

function ClearAuth() {
  const { clearAuthData } = useWristbandAuth();
  
  const reauthenticate = () => {
    clearAuthData();
    redirectToLogin('https://your-server.com/api/auth/login');
  };
  
  return (
    <div>
      <h2>Clear Authentication Data</h2>
      <button onClick={() => reauthenticate()}>
        Re-Authenticate
      </button>
    </div>
  );
}

useWristbandSession()

This hook provides access to the authenticated user's session data:

  • userId: The authenticated user's ID.
  • tenantId: The ID of the tenant that the authenticated user belongs to.
  • metadata: Opional custom session metadata provided by your backend, if applicable (profile info, roles, etc.)
  • updateMetadata(): Function to modify the metadata object stored in the client-side React Context. This enables real-time UI updates with new metadata values, but it is limited to the current browser session only. Any changes made with this function will not persist across page refreshes or be synchronized to your backend server.

Use this hook when you need access to the user data provided by your backend's Session Endpoint. It helps you build personalized experiences based on the specific user information your server makes available.

import { useWristbandSession } from '@wristband/react-client-auth';

function UserProfile() {
  const { userId, tenantId, metadata, updateMetadata } = useWristbandSession();
  
  const handleNameUpdate = (newName) => {
    updateMetadata({ name: newName });
  };
  
  return (
    <div>
      <h2>User Profile</h2>
      <p>User ID: {userId}</p>
      <p>Tenant: {tenantId}</p>
      
      <h3>User Details</h3>
      <p>Name: {metadata.name}</p>
      <p>Email: {metadata.email}</p>
      <p>Role: {metadata.role}</p>
      
      <button onClick={() => handleNameUpdate("New Name")}>
        Update Name
      </button>
    </div>
  );
}

For TypeScript applications, you can leverage type safety when working with session metadata. By providing a type parameter to the useWristbandSession hook, you can ensure that your metadata object and update functions are properly typed. This approach ensures proper IDE autocomplete suggestions for metadata properties as well as compile-time type checking for the values you pass to updateMetadata.

import { useWristbandSession } from '@wristband/react-client-auth';

interface UserPreferences {
  theme: 'light' | 'dark';
  notifications: boolean;
  language: string;
}

function PreferencesPanel() {
  const { metadata, updateMetadata } = useWristbandSession<UserPreferences>();
  
  const toggleTheme = () => {
    const newTheme = metadata.theme === 'light' ? 'dark' : 'light';
    updateMetadata({ theme: newTheme });
  };
  
  return (
    <div>
      <h2>Your Preferences</h2>
      <button onClick={toggleTheme}>
        Switch to {metadata.theme === 'light' ? 'Dark' : 'Light'} Mode
      </button>
      
      <label>
        <input 
          type="checkbox"
          checked={metadata.notifications}
          onChange={(e) => updateMetadata({ notifications: e.target.checked })}
        />
        Enable Notifications
      </label>
    </div>
  );
}

3) Use Token Hook (Optional)

When following Wristband’s backend server integration pattern, the recommended approach is to protect your backend APIs by relying solely on the session cookie, which the browser automatically includes with each request. Your backend should use middleware to validate the session, verify the CSRF token, and refresh expired tokens if necessary. This is the most secure way to protect your backend.

Alternatively, the React SDK can extract the access token from the authenticated session and cache it client-side. This enables developers to send access tokens manually in the Authorization header for outgoing API requests. In this model, your backend should use middleware that checks for a Bearer token in the Authorization header and validates the JWT. While this approach is slightly less secure than relying entirely on session cookies, it is still more secure than storing tokens in local storage. The benefit is greater flexibility to make API calls directly from the browser without having to route every request through a backend-for-frontend (BFF) layer.

useWristbandToken()

The useWristbandToken() hook exposes functionality for maanging client-side access tokens:

  • getToken(): Retrieves a valid access token for making authenticated API calls to resource servers. Returns a cached token if available and not expired, otherwise fetches a fresh token from the configured tokenUrl endpoint. The access token does not persist across page navigations or refreshes. Your server's Token Endpoint is responsible for refreshing expired tokens by using the user's session state.
  • clearToken(): Function to modify the metadata object stored in the client-side React Context. This enables real-time UI updates with new metadata values, but it is limited to the current browser session only. Any changes made with this function will not persist across page refreshes or be synchronized to your backend server.

In order to use this hook, you must first configure the tokenUrl property on the WristbandAuthProvider to point to your server's Token Endpoint:

import { WristbandAuthProvider } from '@wristband/react-client-auth';

function App() {
  return (
    <WristbandAuthProvider
      loginUrl="https://your-server.com/api/auth/login"
      sessionUrl="https://your-server.com/api/v1/session"
      tokenUrl="https://your-server.com/api/v1/token" // Your server's Token Endpoint
    >
      <YourAppComponents />
    </WristbandAuthProvider>
  );
}

From there, you can now leverage the useWristbandToken() hook within your React app:

import axios from 'axios';
import { useWristbandToken } from '@wristband/react-client-auth';

function HelloWorld() {
  const { getToken, clearToken } = useWristbandToken();
  
  const handleHelloWorld = async () => {
    try {
      const token = await getToken();
      const response = await axios.get('https://your-server.com/api/v1/hello-world');
      console.log(`Hello World! ${response.data}`);
    } catch (error) {
      console.error(error);
      clearToken();
    }
  };
  
  return (
    <div>
      <h2>Hello World</h2>
      <button onClick={() => handleHelloWorld()}>
        Say Hello
      </button>
    </div>
  );
}

4) Use Auth Utility Functions

The SDK provides utility functions for handling login and logout redirects, making it easy to implement navigation and error handling. These utility functions handle the details of proper URL formatting and query parameter management, ensuring a consistent and reliable authentication flow throughout your application.

redirectToLogin()

The redirectToLogin function redirects the user to your backend server's Login Endpoint:

import { redirectToLogin } from '@wristband/react-client-auth';

function LoginButton() {
  return (
    <button onClick={() => redirectToLogin('https://your-server.com/api/auth/login')}>
      Sign In
    </button>
  );
}

redirectToLogout()

The redirectToLogout function redirects the user to your backend server's Logout Endpoint:

import { redirectToLogout } from '@wristband/react-client-auth';

function LogoutButton() {
  return (
    <button onClick={() => redirectToLogout('https://your-server.com/api/auth/logout')}>
      Sign Out
    </button>
  );
}

Handling 401 Errors

These utilities are particularly useful for handling authentication errors in your API requests:

import { redirectToLogin } from '@wristband/react-client-auth';
import axios from 'axios';

export function ExampleApiComponent() {
  const executeServerApiCall = async () => {
    try {
      const response = await axios.get('<your-server-resource-api>');
      alert(response);
    } catch (error: unknown) {
      if (axios.isAxiosError(error) && error.response?.status === 401) {
        redirectToLogin('https://your-server.com/api/auth/login');
      } else {
        alert(error);
      }
    }
  }

  return (
    <button onClick={executeServerApiCall}>
      Get Resource
    </button>
  );
}

Transforming Session Metadata

The transformSessionMetadata prop on the WristbandAuthProvider provides a flexible way to reshape the raw session metadata returned from your backend server into a more convenient format for your frontend application.

For example, let's say your backend server's Session Endpoint returns this response format to your React frontend:

{
  "userId": "123",
  "tenantId": "456",
  "metadata": {
    "user_name": "john.doe",
    "email_address": "john.doe@example.com",
    "feature_flags": {
      "beta_features": true,
      "experimental_ui": false
    }
  }
}

You can transform it to a more convenient structure:

import { WristbandAuthProvider } from '@wristband/react-client-auth';

interface RawMetadata {
  user_name: string;
  email_address: string;
  feature_flags?: {
    beta_features?: boolean;
    experimental_ui?: boolean;
  };
}

interface UserMetadata {
  displayName: string;
  email: string;
  features: {
    hasBetaAccess: boolean;
    useExperimentalUI: boolean;
  };
}

function App() {
  return (
    <WristbandAuthProvider<UserMetadata>
      loginUrl="/api/auth/login"
      sessionUrl="/api/auth/session"
      transformSessionMetadata={(rawMetadata: unknown): UserMetadata => {
        const metadata = rawMetadata as RawMetadata;
        return {
          displayName: metadata.user_name,
          email: metadata.email_address,
          features: {
            hasBetaAccess: metadata.feature_flags?.beta_features || false,
            useExperimentalUI: metadata.feature_flags?.experimental_ui || false
          },
        };
      }}
    >
      <YourAppComponents />
    </WristbandAuthProvider>
  );
}

The transformation happens once when the session data is received, making your components cleaner and more focused on presentation rather than data manipulation. Now in your components, you can easily use the transformed data:

import { useWristbandSession } from '@wristband/react-client-auth';

function UserDashboard() {
  const { metadata } = useWristbandSession<UserMetadata>();
  
  return (
    <div className="dashboard">
      <header>
        <h1>Welcome, {metadata.displayName}</h1>
      </header>
      
      {metadata.features.hasBetaAccess && (
        <div className="beta-section">
          <h2>Beta Features</h2>
          <p>You have access to our beta features!</p>
        </div>
      )}
      
      {metadata.features.useExperimentalUI ? (
        <ExperimentalDashboard email={metadata.email} />
      ) : (
        <StandardDashboard email={metadata.email} />
      )}
    </div>
  );
}

Executing Custom Logic After Session Initialization

The onSessionSuccess property on WristbandAuthProvider allows you to execute custom initialization logic when a user's session is successfully retrieved from your server's Session Endpoint. The function is executed after session data is fetched but before the Provider's internal state is updated, making it the perfect place for initialization logic that depends on the user's identity. This is useful for post-authentication tasks including data prefetching, service configuration, global state initialization, and more.

import { WristbandAuthProvider, SessionResponse } from '@wristband/react-client-auth';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient({});

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <WristbandAuthProvider
        loginUrl="/api/auth/login"
        sessionUrl="/api/v1/session"
        onSessionSuccess={(sessionResponse: SessionResponse) => {
          const { metadata, tenantId, userId } = sessionResponse;

          const { companyConfigs } = metadata;
          queryClient.setQueryData(['company-configs'], companyConfigs);

          initializeAnalytics({ userId, tenantId });
        }}
      >
        <App />
      </WristbandAuthProvider>
    </QueryClientProvider>
  );
}

API Reference

<WristbandAuthProvider<TSessionMetadata>>

import React from 'react';
import { SessionResponse, WristbandAuthProvider } from '@wristband/react-client-auth';

interface UserMetadata {
  name: string;
  email: string;
  isAdmin: boolean;
}

const loadTenantConfig = (id: string) => console.log(`Loading config for tenant ${id}`);

export default function App() {
  return (
    <WristbandAuthProvider<UserMetadata>
      loginUrl="/api/auth/login"
      sessionUrl="/api/auth/session"
      csrfCookieName="CSRF_TOKEN"
      csrfHeaderName="X-CSRF-TOKEN"
      disableRedirectOnUnauthenticated={false}
      transformSessionMetadata={(rawMetadata: unknown): UserMetadata => ({
        name: rawMetadata.display_name || 'User',
        email: rawMetadata.email_address,
        isAdmin: rawMetadata.roles?.includes('admin') || false
      })}
      onSessionSuccess={(session: SessionResponse) => {
        console.log(`User ${session.userId} authenticated`);
        loadTenantConfig(session.tenantId);
      }}
    >
      <div>Your application here</div>
    </WristbandAuthProvider>
  );
}
PropertyTypeRequired?Description
csrfCookieNamestringNoName of the CSRF cookie that the server sets. This enables CSRF protection for the request made to your Session Endpoint.

Default: CSRF-TOKEN
csrfHeaderNamestringNoName of the CSRF header that will be sent with authenticated requests to your Session Endpoint. This should match the header name your server expects for CSRF validation.

Default: X-CSRF-TOKEN
disableRedirectOnUnauthenticatedbooleanNoWhen true, unauthenticated users will remain on the current page instead of being redirected to your backend server's Login or Logout Endpoints. This is useful for public pages that have both authenticated and unauthenticated states.

Default: false
loginUrlstringYesThe URL of your backend server's Login Endpoint that handles the authentication flow with Wristband.
onSessionSuccess(sessionResponse: SessionResponse) => Promise<void> | voidNoFunction that executes after a successful session response but before authentication state updates. If this function returns a Promise, the authentication state update will be delayed until the Promise resolves. This is useful for post-authentication tasks including data prefetching, service configuration, global state initialization, and more.
sessionUrlstringYesThe URL of your server's Session Endpoint, which returns an authenticated user's userId, tenantId, and any optional metadata.
transformSessionMetadata(rawSessionMetadata: unknown) => TSessionMetadataNoFunction to transform raw metadata from the session response before storing it in context. Useful for converting data types, adding computed properties, filtering unnecessary properties, and ensuring type safety.

Hooks

useWristbandAuth()

import { useWristbandAuth } from '@wristband/react-client-auth';

function AuthHook() {
  const { authError, authStatus, clearAuthData, isAuthenticated, isLoading } = useWristbandAuth();
  
  return (
    <div>
      <p>authStatus: {authStatus}</p>
      <p>authError: {authError ? authError.message : 'None'}</p>
      <p>isAuthenticated: {isAuthenticated}</p>
      <p>isLoading: {isLoading}</p>
      <button onClick={() => clearAuthData()}>
        Clear Auth Data
      </button>
    </div>
  );
}
FieldTypeDescription
authErrorWristbandError or nullAn error object details when session fetching or authentication fails. Provides error codes and messages for debugging. Only populated when disableRedirectOnUnauthenticated is true; otherwise, users are redirected to login on errors. If no error is encountered, then the value is null.
authStatusAuthStatus (enum)Represents the current authentication status.

Possible values: LOADING, AUTHENTICATED, or UNAUTHENTICATED.
clearAuthData() => voidThis function clears all client-side auth state including authentication status, user data, session metadata, cached tokens, and errors.
isAuthenticatedbooleanA boolean indicator that is true when the user is authenticated and false otherwise.
isLoadingbooleanA boolean indicator that is true when the authentication status is still being determined (e.g., during the initial session check) and false once the status is determined.

In the event an authError occurs, the WristbandError can have any of the following error codes:

Wristband Error CodeDescription
INVALID_LOGIN_URLAn invalid login URL value was provided to the SDK.
INVALID_LOGOUT_URLAn invalid logout URL value was provided to the SDK (primarily for redirectToLogout()).
INVALID_SESSION_RESPONSEThe session endpoint response is missing required fields.
INVALID_SESSION_URLAn invalid session URL value was provided to the SDK.
INVALID_TOKEN_RESPONSEThe token endpoint response is missing required fields.
INVALID_TOKEN_URLAn invalid token URL value was provided to the SDK (only occurs if using getToken()).
SESSION_FETCH_FAILEDThe session endpoint returned an error other than 401.
TOKEN_FETCH_FAILEDThe token endpoint returned an error other than 401.
UNAUTHENTICATEDThe user is not authenticated and cannot request a session or token (typicaly from a 401 error).

useWristbandSession<TSessionMetadata>()

import { useWristbandSession } from '@wristband/react-client-auth';

type UserMetadata = {
  name: string;
  email: string;
};

function SessionHook() {
  const { userId, tenantId, metadata, updateMetadata } = useWristbandSession<UserMetadata>();
  
  return (
    <div>
      <p>userId: {userId}</p>
      <p>tenantId: {tenantId}</p>
      <p>name: {metadata.name}</p>
      <p>email: {metadata.email}</p>
      <button onClick={() => updateMetadata({ name: 'New Name' })}>
        Update Name
      </button>
    </div>
  );
}
FieldTypeDescription
metadataTSessionMetadataOptional custom user metadata with type safety. You can define this type by providing a generic type parameter to both the provider (<WristbandAuthProvider<YourType>>) and this hook (useWristbandSession<YourType>()). When used with the transformSessionMetadata() function, the metadata will conform to the type you've specified.

Default type: unknown
tenantIdstringThe identifier for the tenant the user belongs to.
updateMetadata(newMetadata: Partial<TSessionMetadata>) => voidA function that lets you update the metadata object with type-safe partial updates. The type parameter you provide to the hook ensures that any updates you make are compatible with your defined metadata structure. This only updates the client-side state and does not persist changes to the server.
userIdstringThe unique identifier for the authenticated user.

useWristbandToken()

import { useWristbandToken } from '@wristband/react-client-auth';

function TokenHook() {
  const { clearToken, getToken } = useWristbandToken();
  
  return (
    <div>
      <button onClick={() => getToken()}>
        Get Token
      </button>
      <button onClick={() => clearToken()}>
        Clear Token
      </button>
    </div>
  );
}
FieldTypeDescription
clearToken() => voidClears the cached access token and forces the next getToken() call to fetch a fresh token, assuming that the user still has a valid session cookie.
getToken() => voidRetrieves a valid access token for making authenticated API calls to resource servers. Returns a cached token if available and not expired; otherwise fetches a fresh token from the configured "tokenUrl" endpoint. Your server's Token Endpoint should automatically handle token expiration and refresh using the user's session cookie.

Utility Functions

redirectToLogin(loginUrl: string, config?: LoginRedirectConfig): void

import { redirectToLogin } from '@wristband/react-client-auth';

function handleLogin() {
  redirectToLogin('https://your-server.com/api/auth/login', {
    loginHint: 'user@company.com',
    returnUrl: window.location.href,
    tenantDomain: 'acme-corp',
    tenantCustomDomain: 'auth.acme.com'
  });
}
Login Redirect ConfigTypeRequired?Description
loginHintstringNoPre-fills the Tenant Login Page form with a specific username or email. Sent as the login_hint query parameter to your Login Endpoint.
returnUrlstringNoURL to redirect back to after successful authentication. Sent as the return_url query parameter to your Login Endpoint.
tenantCustomDomainstringNoTenant custom domain for routing to the correct Tenant Login Page. Sent as the tenant_custom_domain query parameter to your Login Endpoint.
tenantDomainstringNoTenant domain name for routing to the correct Tenant Login Page. Sent as the tenant_domain query parameter to your Login Endpoint.

redirectToLogout(logoutUrl: string, config?: LogoutRedirectConfig): void

import { redirectToLogout } from '@wristband/react-client-auth';

function handleLogout() {
  redirectToLogout('https://your-server.com/api/auth/logout', {
    tenantDomain: 'acme-corp',
    tenantCustomDomain: 'auth.acme.com'
  });
}
Logout Redirect ConfigTypeRequired?Description
tenantCustomDomainstringNoTenant custom domain for routing to the correct Tenant Login Page after logout. Sent as the tenant_custom_domain query parameter to your Logout Endpoint.
tenantDomainstringNoTenant domain name for routing to the correct Tenant Login Page after logout. Sent as the tenant_domain query parameter to your Logout Endpoint.

Questions

Reach out to the Wristband team at support@wristband.dev for any questions regarding this SDK.


Keywords

react

FAQs

Package last updated on 22 Aug 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.