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

@sysnormal/react-sso

v1.1.1

Published

SSO authentication provider and utilities for React

Readme

@sysnormal/react-sso

npm GitHub tag License

React TypeScript MUI

AI Assisted

@sysnormal/react-sso is a React library that provides a complete authentication integration with the Sysnormal SSO Server. It manages tokens, session state, default auth screens, social login, and secure HTTP requests — all with minimal setup.

Designed to work standalone or alongside @sysnormal/react-drawer-layout.


🚀 Main Features

  • 🔐 AuthProvider — manages token, refresh token, agent state, and localStorage persistence
  • 🖥️ Default auth screens — Login, Register, and Recover Password with dark/light theme detection
  • 🌍 Social login support — Google and GitHub via OAuth2 (requires Sysnormal SSO Server 1.4.0+)
  • 🔄 Automatic token refresh — transparent retry on expired token with secureFetch
  • 🪝 Hooks for components — useAuth, useSecureFetch, useGetAllowedResources, useGetResourcePermission, useTopBar
  • 🔧 Function for controllers — secureFetchAuth for use outside React components
  • 🧩 Generic agent typing — AuthProvider<TAgent> for full TypeScript inference
  • 🌐 i18n-ready — inject your own t() function or use built-in English defaults
  • 🎨 Pluggable response adapter — works with any API response format via responseAdapter

📦 Installation

npm install @sysnormal/react-sso

Peer dependencies (must be installed in your project):

npm install react react-dom @mui/material @mui/icons-material @emotion/react @emotion/styled

⚙️ Global Configuration

Call ssoConfig once at your app's entry point before rendering:

import { ssoConfig, defaultDataSwapAdapter } from '@sysnormal/react-sso';

ssoConfig({
  ssoUrl: 'https://your-sso-server.com',
  ssoThisSystemId: 1,
  responseAdapter: defaultDataSwapAdapter, // use if your SSO returns { success, data, message }
});

ssoConfig options

| Option | Type | Default | Description | |---|---|---|---| | ssoUrl | string | http://localhost | Base URL of the SSO server | | ssoAuthEndpoint | string | /auth/login | Login endpoint | | ssoRefreshTokenEndpoint | string | /auth/refresh_token | Token refresh endpoint | | ssoRegisterEndpoint | string | /auth/register | Registration endpoint | | ssoGetAllowedResourcesEndpoint | string | /records/resources/get_alloweds | Allowed resources endpoint | | ssoGetResourcePermissionsEndpoint | string | /records/resources/get_resource_permissions | Resource permissions endpoint | | ssoThisSystemId | number | undefined | ID of the current system in the SSO | | responseAdapter | ResponseAdapter | undefined | Custom response parser | | appLogo | ReactNode | undefined | Logo shown on auth screens | | appTitle | string | undefined | Title shown on auth screens | | themeMode | 'light' \| 'dark' | auto-detected | Default theme mode for auth screens | | translater | (key: string) => string | built-in English | i18n function for auth screens |


🔌 AuthProvider

Wrap your app with AuthProvider. It controls what is rendered based on authentication state and current route.

import { AuthProvider } from '@sysnormal/react-sso';

export default function App() {
  return (
    <AuthProvider>
      <MyApp />
    </AuthProvider>
  );
}

When not authenticated, the built-in LoginScreen is shown automatically. When authenticated, children is rendered.

Customizing auth screens

<AuthProvider
  loginPage={<MyCustomLoginPage />}       // optional: replace login screen
  registerPage={<MyCustomRegisterPage />} // optional: replace register screen
  recoverPage={<MyCustomRecoverPage />}   // optional: replace recover screen
  appLogo={<img src="/logo.png" />}       // shown on default screens
  appTitle="My System"
  socialLogins={[
    { provider: 'google', redirectUri: 'https://myapp.com/auth/callback' }
  ]}
>
  <MyApp />
</AuthProvider>

AuthProvider props

| Prop | Type | Default | Description | |---|---|---|---| | loginPage | ReactNode | built-in LoginScreen | Custom login screen | | registerPage | ReactNode | built-in RegisterScreen | Custom register screen | | recoverPage | ReactNode | built-in RecoverScreen | Custom recover screen | | storage | 'localStorage' \| 'sessionStorage' \| 'none' | 'localStorage' | Token persistence strategy | | loginPath | string | /auth/login | Path that renders the login screen | | registerPath | string | /auth/register | Path that renders the register screen | | recoverPath | string | /auth/recover | Path that renders the recover screen | | publicPrefix | string | /public | Prefix for routes that bypass auth | | appLogo | ReactNode | undefined | Logo for default auth screens | | appTitle | string | undefined | Title for default auth screens | | themeMode | 'light' \| 'dark' | auto-detected | Theme for default auth screens | | socialLogins | SocialLoginConfig[] | undefined | Social login providers |


🪝 Hooks

useAuth

Access the authentication state and actions anywhere inside AuthProvider:

import { useAuth } from '@sysnormal/react-sso';

function MyComponent() {
  const { logged, token, refreshToken, agent, login, logout, onTokenRefreshed } = useAuth();

  return logged
    ? <button onClick={logout}>Sign out</button>
    : <span>Not logged in</span>;
}

You can type the agent for full inference:

type MyAgent = { id: number; email: string; name: string };

const { agent } = useAuth<MyAgent>();
// agent.email is typed

useSecureFetch

Makes authenticated HTTP requests with automatic token injection and refresh. Use inside React components:

import { useSecureFetch } from '@sysnormal/react-sso';

function MyComponent() {
  const secureFetch = useSecureFetch();

  const loadData = async () => {
    const result = await secureFetch({
      url: 'https://my-api.com/data',
      method: 'GET',
    });
    console.log(result.data);
  };
}

Token, refresh token, and logout-on-expiry are injected automatically — no need to pass them manually.


secureFetch

Makes authenticated HTTP requests with automatic token injection and refresh. Use inside and outside React components:

import { secureFetch } from '@sysnormal/react-sso';

function MyComponent() {

  const loadData = async () => {
    const result = await secureFetch({
      url: 'https://my-api.com/data',
      method: 'GET',
    });
    console.log(result.data);
  };
}

useGetAllowedResources

Fetches the resources the logged-in agent is allowed to access:

import { useGetAllowedResources } from '@sysnormal/react-sso';

function AppContent() {
  const getAllowedResources = useGetAllowedResources();

  useEffect(() => {
    (async () => {
      const result = await getAllowedResources({ systemId: 1 });
      if (result.success) {
        console.log(result.data); // flat array of ResourcePermissionData
      }
    })();
  }, []);
}

Use flatToNestedArray to build a tree:

import { flatToNestedArray } from '@sysnormal/react-sso';

const nested = flatToNestedArray(result.data, 'resourceId', 'resourceParentId');

useGetResourcePermission

Checks permissions for a specific resource path:

import { useGetResourcePermission } from '@sysnormal/react-sso';

function MyScreen() {
  const getResourcePermission = useGetResourcePermission();

  useEffect(() => {
    (async () => {
      const result = await getResourcePermission({
        resourcePath: '/views/modules/dashboard',
      });
      if (result.success && result.data?.[0]?.resourcePermissionAllowedAccess) {
        // user has access
      }
    })();
  }, []);
}

🖥️ Default Auth Screens

The library ships built-in screens that work out of the box. They auto-detect the system theme (dark/light) and respect the user's manual toggle stored in localStorage.

LoginScreen

| Prop | Type | Description | |---|---|---| | logo | ReactNode | Logo displayed above the title | | title | string | Screen title | | theme | Theme | MUI theme override | | socialLogins | SocialLoginConfig[] | Social login providers | | registerPath | string | Link to register screen | | recoverPath | string | Link to password recovery screen | | onSuccess | function | Called after successful login | | onError | function | Called on login error | | slots | AuthScreenSlots | Override header, footer, or extra fields | | t | (key: string) => string | i18n function |

RegisterScreen and RecoverScreen

Same props as LoginScreen except socialLogins is also available on RegisterScreen and there is no recoverPath on RecoverScreen.


🌍 Social Login

Social login requires the Sysnormal SSO Server with Google (1.4.0+) or GitHub (1.5.0+) configured.

Configure providers in AuthProvider or on the LoginScreen directly:

<AuthProvider
  socialLogins={[
    {
      provider: 'google',
      redirectUri: 'https://myapp.com/auth/callback',
      label: 'Continue with Google',
      icon: <GoogleIcon />,
    },
    {
      provider: 'github',
      redirectUri: 'https://myapp.com/auth/callback',
      label: 'Continue with GitHub',
      icon: <GitHubIcon />,
    },
  ]}
>

On the callback route, use useSocialLoginCallback:

import { useSocialLoginCallback } from '@sysnormal/react-sso';

function CallbackPage() {
  const { loading, error } = useSocialLoginCallback();

  if (loading) return <CircularProgress />;
  if (error) return <Alert severity="error">{error}</Alert>;
  return null; // AuthProvider redirects automatically after login
}

OAuth2 Social Login Flow

+----------+          +-----------+          +----------+
|  Frontend |          |  SSO      |          | Google/  |
|           |          |  Server   |          | GitHub   |
+----------+          +-----------+          +----------+
     |                      |                     |
     |-- (1) GET login URL ->|                     |
     |<- (2) URL returned ---|                     |
     |                      |                     |
     |-- (3) Redirect user to provider URL ------->|
     |                      |     (4) User auths --|
     |<- (5) Redirect back with ?code=XYZ ---------|
     |                      |                     |
     |-- (6) Send code to SSO (/auth/*/handle_code)|
     |       -------------->|                     |
     |                      |-- (7) Exchange code >|
     |                      |<- (8) Token + info --|
     |                      |-- (9) Save user      |
     |<- (10) SSO JWT token-|                     |
     |                      |                     |

🧩 Response Adapter

If your API returns a custom response format, implement ResponseAdapter:

import { ResponseAdapter, FetchCoreResult, ssoConfig } from '@sysnormal/react-sso';

const myAdapter: ResponseAdapter = (raw: any, httpStatus): FetchCoreResult => ({
  success: raw.ok ?? httpStatus < 400,
  status: httpStatus,
  data: raw.result,
  message: raw.errorMessage,
});

ssoConfig({ responseAdapter: myAdapter });

The built-in defaultDataSwapAdapter is provided for APIs that return { success, data, message, exception } (compatible with @aalencarv/common-utils DefaultDataSwap).


👤 UserMenu Component

A ready-to-use avatar button for the top bar that shows the agent's initial and a logout menu:

import { UserMenu } from '@sysnormal/react-sso';

// use inside topBarProps.actions of @sysnormal/react-drawer-layout
<RootLayout
  topBarProps={{
    actions: <UserMenu logoutLabel="Sign out" />
  }}
>

The logout() from useAuth is called automatically, clearing all stored tokens and returning to the login screen.


🔁 Token Refresh Flow

+----------+       +-----------+       +-----------+
| Frontend |       | secureFetch|       |  SSO      |
+----------+       +-----------+       +-----------+
     |                  |                   |
     |-- request ------->|                   |
     |                  |-- fetch with token>|
     |                  |<- 401 expired -----|
     |                  |                   |
     |                  |-- refresh token -->|
     |                  |<- new token -------|
     |                  |                   |
     |                  |-- retry request -->|
     |                  |<- success ---------|
     |<- result ---------|                   |

Handled transparently by secureFetch and secureFetchAuth. If the refresh token is also expired, logout() is called automatically.


🧰 Technologies Used

  • React 18+
  • TypeScript 5+
  • MUI (Material UI) 6+
  • JSON Web Token (JWT)

🧬 Clone the repository

git clone https://github.com/sysnormal1/react-sso.git
cd react-sso
npm install

🔧 Build

npm run build

🧪 Tests

npm test

⚖️ License

This project is licensed under the ISC License — see the LICENSE file for details.


👤 Author

Alencar Velozo GitHub: @aalencarvz1


🏢 Organization

Sysnormal GitHub: @sysnormal1


Acknowledgements

Parts of this project were developed with the assistance of AI-based tools for code generation, review and documentation.