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

@cyberia-auth/auth

v0.1.18

Published

Cyberia Auth React components and provider

Readme

@cyberia-auth/auth

React auth SDK for Cyberia Auth.

It includes:

  • Full-page authCyberiaAuth (sign-in / sign-up, email + OAuth).
  • Provider + sessionCyberiaAuthProvider, useCyberiaAuth() (modal auth, OAuth return handling, optional embedded RBAC when apiToken is set).
  • Workspace invitesCyberiaWorkspaceInvitation for Auth Admin URLs such as /invite?invite_status=ready&invite_token=....
  • Route / layout guardsProtect, SignedIn, SignedOut, Show.
  • ChromeUserButton, SignInButton, SignUpButton, SignOutButton.
  • Permission helpers (re-exported)hasEmbeddedAppPermission, normalizeEmbeddedMatrix, DEFAULT_EMBEDDED_MATRIX, DEFAULT_EMBEDDED_RESOURCE_CATALOG, and types for building your own settings UI or tests.
  • App user management (admin API)CyberiaUserSettings / UserSettings — list end users, pending approvals, add/remove memberships for one app.

Installation

npm install @cyberia-auth/auth

Peer dependencies:

  • react ^18 || ^19
  • react-dom ^18 || ^19

Components and exports (quick map)

| Export | Type | When to use | |--------|------|-------------| | CyberiaAuthProvider | Provider | Wrap the app; holds session, theme, optional embedded matrix from public config. | | useCyberiaAuth | Hook | Read session, open modals, signOut, canAppEmbedded, setAppOperatorRole, … | | CyberiaAuth | Page / modal body | Full login/register card (used inside the provider modal or on a dedicated /login route). | | CyberiaWorkspaceInvitation | Page | Auth Admin “accept workspace invite” flow. | | Protect | Guard | Render children or fallback by sign-in state (e.g. React Router). | | SignedIn / SignedOut | Guard | Render children only when signed in or signed out. | | Show | Guard | Same idea with an explicit when="signed-in" \| "signed-out". | | UserButton | UI | Avatar menu + manage-account shell. | | SignInButton / SignUpButton / SignOutButton | UI | Trigger modals or sign-out. | | hasEmbeddedAppPermission, … | Pure helpers | Unit tests or server-free UI previews of permission matrices. | | CyberiaUserSettings / UserSettings | Page | apiToken + user JWT (userToken or adminToken / localStorage — user type is detected) or admin JWT + apiToken / app picker. |

Environment variables example

VITE_CYBERIA_APP_TOKEN=app_your_token_here
VITE_CYBERIA_OAUTH_REDIRECT=https://your-app-domain.com/protected

Quick start (provider + route guard)

import {
  CyberiaAuthProvider,
  SignedIn,
  SignedOut,
  SignInButton,
  SignUpButton,
  UserButton,
  Protect,
} from '@cyberia-auth/auth';

const backendUrl = import.meta.env.VITE_CYBERIA_BACKEND_URL;
const apiToken = import.meta.env.VITE_CYBERIA_APP_TOKEN;
const oauthRedirectUri = import.meta.env.VITE_CYBERIA_OAUTH_REDIRECT;

function App() {
  return (
    <CyberiaAuthProvider
      backendUrl={backendUrl}
      apiToken={apiToken}
      oauthRedirectUri={oauthRedirectUri}
      theme="system"
    >
      <header style={{ display: 'flex', gap: 8 }}>
        <SignedOut>
          <SignInButton />
          <SignUpButton />
        </SignedOut>
        <SignedIn>
          <UserButton />
        </SignedIn>
      </header>

      <Protect fallback={<p>Please sign in.</p>}>
        <div>Protected content</div>
      </Protect>
    </CyberiaAuthProvider>
  );
}

Embedded page example (CyberiaAuth)

Use this when you want a full login page instead of only modal buttons.

import { type AuthResult, CyberiaAuth, useCyberiaAuth } from '@cyberia-auth/auth';
import { useNavigate } from 'react-router-dom';

const API_TOKEN = import.meta.env.VITE_CYBERIA_APP_TOKEN;

export default function LoginPage() {
  const navigate = useNavigate();
  const { setSessionFromAuth } = useCyberiaAuth();

  return (
    <CyberiaAuth
      apiToken={API_TOKEN}
      oauthRedirectUri={window.location.origin}
      initialMode="login"
      theme="system"
      onAuthSuccess={(result: AuthResult) => {
        setSessionFromAuth(result);
        navigate('/', { replace: true });
      }}
    />
  );
}

SignedIn / SignedOut example

import { SignedIn, SignedOut, SignInButton, UserButton } from '@cyberia-auth/auth';

function HeaderActions() {
  return (
    <>
      <SignedOut>
        <SignInButton />
      </SignedOut>
      <SignedIn>
        <UserButton />
      </SignedIn>
    </>
  );
}

Show example (explicit when)

Show is equivalent to SignedIn / SignedOut but accepts a single when prop (useful when the condition is chosen at runtime).

import { Show, UserButton, SignInButton } from '@cyberia-auth/auth';

function Toolbar({ preferAccountMenu }: { preferAccountMenu: boolean }) {
  return (
    <>
      <Show when="signed-out">
        <SignInButton />
      </Show>
      <Show when="signed-in">
        {preferAccountMenu ? <UserButton /> : <span>Welcome</span>}
      </Show>
    </>
  );
}

Embedded app permissions (canAppEmbedded)

For consumer apps that use the same apiToken as your Cyberia application, the provider loads GET /api/public/app/config and exposes:

  • embeddedRolePermissionMatrix — effective CRUD matrix merged from server defaults + Admin overrides.
  • embeddedPermissionResources — display metadata (id, label, description) for end_users, invitations, app_settings.
  • appOperatorRole / setAppOperatorRole(role) — role key for the current operator (e.g. staff member). Must match keys in the matrix (owner, admin, collaborator, or custom keys you configure in Cyberia Auth Admin).
  • defaultAppOperatorRole — optional prop on CyberiaAuthProvider (default collaborator) until you call setAppOperatorRole.
  • canAppEmbedded(resource, action)resource: 'end_users' | 'invitations' | 'app_settings'; action: 'read' | 'create' | 'update' | 'delete'.

If apiToken is omitted, embeddedRolePermissionMatrix is null and canAppEmbedded returns true for everything (no client-side gating).

Provider + staff role from your API

import { useEffect } from 'react';
import {
  CyberiaAuthProvider,
  useCyberiaAuth,
} from '@cyberia-auth/auth';

const backendUrl = import.meta.env.VITE_CYBERIA_BACKEND_URL;
const apiToken = import.meta.env.VITE_CYBERIA_APP_TOKEN;

function App() {
  return (
    <CyberiaAuthProvider
      backendUrl={backendUrl}
      apiToken={apiToken}
      oauthRedirectUri={window.location.origin}
      defaultAppOperatorRole="collaborator"
    >
      <StaffRoleSync />
      <YourRoutes />
    </CyberiaAuthProvider>
  );
}

/** Map your signed-in staff profile to the role keys configured in Cyberia Auth Admin (embedded matrix). */
function StaffRoleSync() {
  const { setAppOperatorRole } = useCyberiaAuth();

  useEffect(() => {
    const roleKey = getStaffEmbeddedRoleKeyFromYourApp();
    if (roleKey) {
      setAppOperatorRole(roleKey);
    }
  }, [setAppOperatorRole]);

  return null;
}

function getStaffEmbeddedRoleKeyFromYourApp(): string | null {
  // Example: read from your JWT, session store, or GET /api/me — must match matrix keys (e.g. admin, collaborator).
  return null;
}

Gating buttons and routes

import { useCyberiaAuth } from '@cyberia-auth/auth';

function InvitationsCard() {
  const { canAppEmbedded } = useCyberiaAuth();

  return (
    <section>
      <h2>Invitations</h2>
      {canAppEmbedded('invitations', 'read') && <InvitationList />}
      {canAppEmbedded('invitations', 'create') && (
        <button type="button">Invite user</button>
      )}
      {canAppEmbedded('invitations', 'delete') && (
        <button type="button">Revoke selected</button>
      )}
    </section>
  );
}

Labels for a “Roles & permissions” settings screen

import { useCyberiaAuth } from '@cyberia-auth/auth';

function PermissionLegend() {
  const { embeddedPermissionResources } = useCyberiaAuth();

  return (
    <ul>
      {embeddedPermissionResources.map((r) => (
        <li key={r.id}>
          <strong>{r.label}</strong> — {r.description}
        </li>
      ))}
    </ul>
  );
}

Testing and previews without the provider

import {
  hasEmbeddedAppPermission,
  normalizeEmbeddedMatrix,
  type EmbeddedRolePermissionMatrix,
} from '@cyberia-auth/auth';

const matrix: EmbeddedRolePermissionMatrix = normalizeEmbeddedMatrix({
  collaborator: { invitations: { delete: true } },
});

const canDelete = hasEmbeddedAppPermission(matrix, 'collaborator', 'invitations', 'delete');

Configure matrices in Cyberia Auth Admin: organization Role permissions (workspace) vs application Embedded role permissions (this SDK reads the app matrix from public config for your apiToken).

App user management (CyberiaUserSettings / UserSettings)

Two ways to authenticate:

  1. App user session (recommended for product UIs) — pass userToken={token} from useCyberiaAuth() (a type: user JWT) plus apiToken. Calls /api/public/app/app-users?apiToken=… with your user session. Workspace admins must enable canManageAppUsers on your app membership (PATCH /api/admin/app-users/:id in Cyberia).
  2. Workspace admin — pass adminToken ( type: admin JWT) and either apiToken (resolves app via GET /v1/environment) or appId / app dropdown.

If apiToken is set and the bearer you pass as adminToken (or via tokenFromLocalStorage) is a type: user JWT, the component uses the same public /api/public/app/app-users flow as userToken — so a product page can pass the sign-in session token as adminToken without getting 401 on /api/admin/app-users.

Membership status: active, pending_approval, unregistered.

With useCyberiaAuth() + application token (same session as your app)

import { CyberiaAuthProvider, CyberiaUserSettings, useCyberiaAuth } from '@cyberia-auth/auth';

const APP_TOKEN = import.meta.env.VITE_CYBERIA_APP_TOKEN;

function UserAdminPage() {
  const { token } = useCyberiaAuth();

  return (
    <CyberiaUserSettings
      userToken={token ?? ''}
      apiToken={APP_TOKEN}
      layout="tabs"
      theme="system"
      branding={{ primaryColor: '#c91111', appName: 'Member management' }}
    />
  );
}

export default function App() {
  return (
    <CyberiaAuthProvider
      backendUrl={import.meta.env.VITE_CYBERIA_BACKEND_URL}
      apiToken={APP_TOKEN}
      oauthRedirectUri={window.location.origin}
    >
      <UserAdminPage />
    </CyberiaAuthProvider>
  );
}

backendUrl on CyberiaUserSettings is optional (defaults to https://auth.cyberia.host); set it if your provider uses a custom backendUrl.

Workspace admin mode

Use adminToken instead of userToken, with apiToken and/or appId / dropdown. Requires workspace app users permissions. See API_USAGE.md.

Reading the session token from localStorage

tokenFromLocalStorage reads the token field from CyberiaAuthProvider’s session (default key cyberia_auth_session). With apiToken, a type: user JWT is routed to the public member-management API; a type: admin JWT still uses /api/admin/app-users.

Custom sign-out button example

If you already have your own sidebar/menu UI:

import { useNavigate } from 'react-router-dom';
import { useCyberiaAuth } from '@cyberia-auth/auth';

function SidebarLogoutButton() {
  const navigate = useNavigate();
  const { signOut } = useCyberiaAuth();

  return (
    <button
      type="button"
      onClick={() => {
        signOut();
        navigate('/login', { replace: true });
      }}
    >
      Logout
    </button>
  );
}

React Router example with Protect

import { Navigate, Route, Routes } from 'react-router-dom';
import { Protect } from '@cyberia-auth/auth';

function AppRoutes() {
  return (
    <Routes>
      <Route path="/login" element={<LoginPage />} />
      <Route
        path="/"
        element={
          <Protect fallback={<Navigate to="/login" replace />}>
            <HomePage />
          </Protect>
        }
      />
    </Routes>
  );
}

SSO sign-up vs sign-in

The component sends intent=sign_up on OAuth start when the user is on Sign up, and intent=sign_in on Sign in (matches Cyberia Auth backend behavior).

If the app uses approval_required sign-up mode, SSO registration returns with signup_status=pending_approval (no JWT). The SDK shows a “Sign-up request pending” dialog (via document.body portal) with OK, which closes the notice without forcing another dialog. The same dialog appears after email/password register when the API responds with 202 and pendingApproval.

OAuth redirect URLs should match oauthRedirectUri (usually your app origin or dedicated callback route) so return query params are read correctly.

Workspace invitation page (CyberiaWorkspaceInvitation)

Use a dedicated route (for example /invite) when the Cyberia Auth backend sends invite links to your Auth Admin UI. Set workspaceInvitationAcceptRedirect on each application in Admin (POST / PATCH /api/admin/apps/:id) — the server picks the URL from the invited apps (see Cyberia Auth API_USAGE.md). Example base: https://your-admin.example.com/invite/.

Short links (current backend): the email and GET /api/admin/workspace-invitations/accept redirect only invite_status=ready and invite_token. The component calls GET /api/admin/workspace-invitations/preview?token=... to load email, role, workspace names, org/app scope (so the URL stays small).

Legacy links may still include workspace_names, invite_email, etc. in the query string; those are used directly and preview is skipped.

Prefer searchParams={useSearchParams()[0]} from React Router; if omitted, the component reads window.location.search each render.

| Parameter | Purpose | |-----------|---------| | invite_status | Failure: invalid_token vs invalid_or_expired / expired. ready (or omitted with token) → accept flow. | | invite_token (or token) | Secret token for preview + POST /api/admin/workspace-invitations/accept | | Other invite_* / workspace_* | Optional; legacy. If workspace_names is absent, details come from preview. |

Minimal page (React Router)

import { useSearchParams } from 'react-router-dom';
import { CyberiaWorkspaceInvitation } from '@cyberia-auth/auth';

export default function AcceptInvite() {
  const [searchParams] = useSearchParams();

  return (
    <CyberiaWorkspaceInvitation
      searchParams={searchParams}
      backendUrl={import.meta.env.VITE_CYBERIA_BACKEND_URL}
      branding={{ appName: 'CYBERIA SOFTWARE', primaryColor: '#c91111' }}
      signInHref="/login"
      successRedirectHref="/"
      onAcceptSuccess={(data) => {
        localStorage.setItem(
          'cyberia_auth_session',
          JSON.stringify({
            token: data.token,
            user: {
              id: data.admin.id,
              email: data.admin.email,
              displayName: data.admin.name,
            },
          })
        );
      }}
    />
  );
}

successRedirectHref shows a short “You’re in!” state then replaces the location (same idea as a manual setTimeout + navigate). Use onAcceptSuccess only and call useNavigate() yourself if you prefer client-side routing without a full reload.

For tests, pass searchParams={new URLSearchParams('invite_status=ready&invite_token=…')} (or searchParamsOverride — same behavior).

API reference

CyberiaAuth props

  • backendUrl?: string — backend base URL (default: https://auth.cyberia.host)
  • apiToken?: string — application token for GET /api/public/app/config, public OAuth, and related flows (see authScope).
  • authScope?: 'public' | 'admin' — default 'public'; controls which auth endpoints the UI calls.
  • allowRegister?: boolean — default true. Set false to hide sign-up (footer “Sign up” and register mode).
  • branding?: { appName?, organizationName?, primaryColor?, secondaryColor?, logoUrl?, oauthProviders?, publicSignUpMode? } — optional UI override; publicSignUpMode mirrors backend when you want to force messaging without refetching config
  • oauthRedirectUri?: string — absolute URL the backend redirects to after OAuth (must be allow-listed on the app / server)
  • initialMode?: 'login' | 'register' — default 'register'
  • theme?: 'system' | 'light' | 'dark' — default 'system'
  • hideModeSwitch?: boolean — hide footer switch between sign in and sign up
  • onAuthSuccess?: (result) => void — callback with { token, user } where user includes avatarUrl when the API provides it (public); admin responses are normalized to the same shape

CyberiaAuthProvider props

  • backendUrl?: string
  • apiToken?: string — set for public app branding/OAuth and for embedded permissions (canAppEmbedded); see authScope.
  • authScope?: 'public' | 'admin'
  • allowRegister?: boolean — default true; set false to disable sign-up in the modal.
  • branding?: { appName?, organizationName?, primaryColor?, secondaryColor?, logoUrl?, oauthProviders?, publicSignUpMode? } — passed to modal auth UI
  • oauthRedirectUri?: string
  • theme?: 'system' | 'light' | 'dark' — applied to modal auth + user menu UI
  • children: ReactNode
  • storageKey?: string — localStorage key (default: cyberia_auth_session)
  • defaultAppOperatorRole?: string — initial role key for canAppEmbedded (default collaborator); override with setAppOperatorRole when you know the signed-in operator’s role.

CyberiaWorkspaceInvitation props

  • backendUrl?: string
  • branding?: { appName?, organizationName?, primaryColor?, secondaryColor?, logoUrl? }
  • searchParams?: URLSearchParams — recommended; e.g. useSearchParams()[0] from React Router
  • searchParamsOverride?: URLSearchParams — deprecated alias of searchParams
  • onAcceptSuccess?: (payload) => voidpayload includes token, admin, workspace, workspaces from the API
  • onAcceptError?: (message: string) => void — optional (e.g. toast); errors are also shown inline
  • successRedirectHref?: string — after success, brief confirmation then window.location.replace(href)
  • successRedirectDelayMs?: number — default 1500
  • signInHref?: string — e.g. /login for Sign in instead / Go to Login
  • onSignInInstead?: () => void — if set, called instead of navigating to signInHref

useCyberiaAuth() returns

  • isLoaded
  • isSignedIn
  • user{ id, email, displayName, avatarUrl? } (avatarUrl when returned by the API or OAuth redirect)
  • token
  • openSignIn()
  • openSignUp()
  • signOut()
  • setSessionFromAuth(result)
  • theme
  • embeddedRolePermissionMatrix — from GET /api/public/app/config when apiToken is set; null without a token (then canAppEmbedded allows all).
  • embeddedPermissionResources — labels for end_users, invitations, app_settings.
  • appOperatorRole / setAppOperatorRole(role) — operator role key for the matrix (see Embedded app permissions above for full examples).
  • canAppEmbedded(resource, action)resource: 'end_users' | 'invitations' | 'app_settings'; action: 'read' | 'create' | 'update' | 'delete'.

Helper components

  • SignedIn — render children only when authenticated
  • SignedOut — render children only when signed out
  • Showwhen="signed-in" | "signed-out" (see example above)
  • SignInButton — opens sign-in modal
  • SignUpButton — opens sign-up modal
  • SignOutButton — clears session
  • UserButton — avatar dropdown + manage account modal
  • Protect — route/content guard with fallback

Re-exported permission utilities

Useful for tests or custom admin UIs: hasEmbeddedAppPermission, normalizeEmbeddedMatrix, DEFAULT_EMBEDDED_MATRIX, DEFAULT_EMBEDDED_RESOURCE_CATALOG, and types EmbeddedAppResourceId, EmbeddedPermissionAction, EmbeddedRolePermissionMatrix, EmbeddedPermissionResourceMeta, EmbeddedResourceCrud.

CyberiaUserSettings / UserSettings props

  • backendUrl?: string — omit for default https://auth.cyberia.host.
  • apiToken?: string / appToken?: string — required for the public member API (with userToken or a detected type: user bearer); resolves appId via GET /v1/environment?apiToken=… (or pass appId for admin-only picker mode).
  • userToken?: string — end-user JWT; uses /api/public/app/app-users (needs canManageAppUsers on your membership).
  • adminToken?: string — workspace admin JWT when the session is not a type: user JWT; with apiToken, a type: user value here still uses the public API.
  • tokenFromLocalStorage?: boolean — read token from localStorage[sessionStorageKey] (default cyberia_auth_session).
  • sessionStorageKey?: string — storage key when using tokenFromLocalStorage (defaults to the provider’s session key).
  • appId?: string — optional when using apiToken; otherwise locks to one app or use neither for a dropdown.
  • layout?: 'tabs' | 'accordion' — default tabs.
  • theme?: 'system' | 'light' | 'dark'
  • branding?: { primaryColor?, appName? }
  • className?, style?

Exported types: AppUserListItem, AppUserMembershipStatus, ExternalAppOption, CyberiaUserSettingsProps.

OAuth notes

  • Configure Google/Microsoft (and other) providers in the Cyberia Admin app (and/or server env) before using social buttons.
  • oauthRedirectUri should be an absolute URL in your app.
  • Which buttons appear: with apiToken, the SDK loads oauthProviders from GET /api/public/app/config?apiToken=... and only renders SSO for those ids. If the backend returns [], the social row is hidden. Older backends without this field still show sensible defaults.
  • After OAuth, the provider reads callback query params (token / admin_token, email / admin_email, displayName / admin_name, optional avatarUrl) and persists the session automatically.

Branding, theme, and flash behavior

  • Component fetches app branding and oauthProviders from /api/public/app/config.
  • Sign-in titles use appName from that response (not organization name).
  • Branding (including oauthProviders when present) is cached per apiToken in localStorage to reduce initial flash.
  • The same automatic config lookup is used for public flows when apiToken is provided.
  • If branding is not available, fallback colors/logo are used.
  • Theme supports system, light, and dark.

Common troubleshooting

  • GET /api/public/app/config?apiToken=... 400: your apiToken is empty or missing while authScope expects a public app token.
  • Redirect to protected route fails after login: ensure setSessionFromAuth(result) is called in custom login page flows.
  • Social login returns but session not applied: verify callback URL and that provider wraps the route tree.

NPM publish steps

1) Build and verify

npm run build
npm pack

2) Login to npm

npm login

3) Publish

npm publish

For first publish on a scope:

npm publish --access public

4) Publish updates

npm run release:patch

Available scripts:

  • release:patch
  • release:minor
  • release:major

Each script runs:

  1. npm version <type>
  2. npm publish --access public

prepublishOnly runs npm run build before publish.