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

@mpofusindie/iam-react

v1.3.1

Published

React hooks and guard components for IAM service

Downloads

871

Readme

@mpofusindie/iam-react

React hooks and guard components for the IAM (Identity & Access Management) service. Provides declarative, permission-based UI rendering with OAuth2/OIDC authentication, two-factor authentication, password reset, and session management.

Install

npm install @mpofusindie/iam-react

Peer dependencies: react >= 18.0.0, react-dom >= 18.0.0, react-router-dom >= 6.0.0

Quick Start

1. Wrap your app with IAMProvider

import { IAMProvider } from "@mpofusindie/iam-react";

function App() {
  return (
    <IAMProvider
      config={{
        apiUrl: "/api/iam/v1",
        token: jwtToken,
        tenantId: "optional-tenant-uuid",     // for header-based multi-tenancy
        refreshMode: "body",                   // "body" | "cookie" | "both"
      }}
      loadingFallback={<Spinner />}
    >
      <YourApp />
    </IAMProvider>
  );
}

2. Guard your routes

import { ProtectedRoute } from "@mpofusindie/iam-react";

<Route path="/loans" element={
  <ProtectedRoute resource="loans">
    <LoansPage />
  </ProtectedRoute>
} />

3. Guard features, actions, and fields

import { FeatureGuard, ActionGuard, FieldGuard } from "@mpofusindie/iam-react";

{/* Show nav item only if user has access to loans */}
<FeatureGuard resource="loans">
  <NavLink to="/loans">Loans</NavLink>
</FeatureGuard>

{/* Show button only if user can create loans */}
<ActionGuard resource="loans" action="create">
  <button>Create Loan</button>
</ActionGuard>

{/* Show button but disabled if no permission */}
<ActionGuard resource="loans" action="approve" mode="disable">
  <button>Approve</button>
</ActionGuard>

{/* Mask sensitive fields */}
<FieldGuard resource="loans" field="ssn" maskChar="***-**-****">
  {loan.ssn}
</FieldGuard>

4. OAuth2 Login

import { useOAuth2, OAuth2LoginButton, OAuth2Callback } from "@mpofusindie/iam-react";

{/* Show provider buttons */}
<OAuth2LoginButton providerKey="google" label="Sign in with Google" />

{/* Handle callback */}
<Route path="/auth/callback" element={
  <OAuth2Callback onSuccess={handleTokens} onError={handleError} />
} />

5. Two-Factor Authentication

import { useTwoFactor, TwoFactorSetup, TwoFactorVerify } from "@mpofusindie/iam-react";

function TwoFactorPage() {
  const { setup, confirmSetup, verify, disable } = useTwoFactor();

  // Setup: generates QR code + backup codes
  const setupData = await setup();

  return (
    <TwoFactorSetup
      setupData={setupData}
      onConfirm={(code) => confirmSetup(code)}
    />
  );
}

// During login challenge (requires2fa === true):
<TwoFactorVerify
  onSubmit={(code) => verify(challengeToken, code)}
  onVerified={(tokenPair) => handleLogin(tokenPair)}
/>

6. Password Reset

import { usePasswordReset, PasswordResetForm } from "@mpofusindie/iam-react";

const { forgotPassword, resetPassword } = usePasswordReset();

<PasswordResetForm
  onForgotPassword={(email) => forgotPassword(email)}
  onResetPassword={(token, password) => resetPassword(token, password)}
  onResetComplete={() => navigate("/login")}
/>

7. Session Management

import { useSessions } from "@mpofusindie/iam-react";

const { revokeUserSessions, revokeTenantSessions } = useSessions();

// Revoke all sessions for a specific user
await revokeUserSessions(userId);

// Emergency: revoke all sessions for the entire tenant
await revokeTenantSessions();

8. Programmatic Permission Checks

import { usePermissions } from "@mpofusindie/iam-react";

function LoansTable() {
  const { canDo, isFieldVisible, hasRole } = usePermissions();

  const columns = baseColumns.filter(
    col => !col.field || isFieldVisible("loans", col.field)
  );

  return (
    <div>
      {canDo("loans", "export") && <ExportButton />}
      <Table columns={columns} data={loans} />
    </div>
  );
}

9. Admin Management API

import { useIAMAdmin } from "@mpofusindie/iam-react";

const admin = useIAMAdmin();

// CRUD operations
const users = await admin.users.list({ page: 0, size: 20 });
const role = await admin.roles.create({ name: "MANAGER", description: "..." });

// OAuth2 providers
const providers = await admin.oauth2Providers.list();
await admin.oauth2Providers.create({ providerKey: "google", ... });

// Audit logs
const logs = await admin.auditLogs.list({ entityType: "USER", from: "2026-01-01" });
const csvBlob = await admin.auditLogs.export("csv", { entityType: "USER" });

// Session management
await admin.sessions.revokeUser(userId);
await admin.sessions.revokeTenant();

API Reference

Components

| Component | Props | Description | |-----------|-------|-------------| | IAMProvider | config, loadingFallback?, onError? | Permission context provider | | FeatureGuard | resource, fallback? | Show children if resource access granted | | ActionGuard | resource, action, mode?, fallback? | Show/disable based on action permission | | FieldGuard | resource, field, fallback?, maskChar? | Show/mask based on field visibility | | ProtectedRoute | resource, redirectTo? | Redirect if access denied | | OAuth2LoginButton | providerKey, label?, icon?, className? | OAuth2 provider login button | | OAuth2Callback | onSuccess, onError, loadingComponent? | OAuth2 callback handler | | TwoFactorSetup | setupData, onConfirm, onError?, className? | 2FA QR code + backup codes + confirm | | TwoFactorVerify | onSubmit, onVerified, onError?, className? | TOTP code input for login challenge | | PasswordResetForm | onForgotPassword, onResetPassword, onResetComplete?, className? | Two-step password reset form |

Hooks

| Hook | Returns | Description | |------|---------|-------------| | usePermissions() | { permissions, loading, canAccess, canDo, isFieldVisible, hasRole, ... } | Permission state and helpers | | useIAMAdmin() | { users, roles, groups, resources, actions, permissions, oauth2Providers, auditLogs, sessions } | Typed CRUD + admin operations | | useOAuth2() | { providers, loading, loginWith, completeAuth, exchangeToken } | OAuth2 authentication flow | | useTwoFactor() | { setup, confirmSetup, verify, disable, regenerateBackupCodes } | 2FA lifecycle management | | usePasswordReset() | { forgotPassword, resetPassword } | Password reset flow | | useSessions() | { revokeUserSessions, revokeTenantSessions } | Session revocation |

Types

import type {
  ResolvedPermissions,
  FeatureAccess,
  FieldAccess,
  ActionPermissions,
  IAMConfig,
  RefreshMode,
  TokenPair,
  OAuth2Provider,
  UserAuthProviderInfo,
  TwoFactorSetupResponse,
  AuditLogEntry,
} from "@mpofusindie/iam-react";

IAMConfig

| Field | Type | Default | Description | |-------|------|---------|-------------| | apiUrl | string | required | IAM backend base URL | | token | string | required | JWT access token | | refreshInterval? | number | — | Auto-refresh interval (ms) | | refreshMode? | RefreshMode | "body" | Refresh token delivery: "body", "cookie", or "both" | | tenantId? | string | — | Tenant UUID for header-based multi-tenancy |

How It Works

  1. IAMProvider fetches GET /me/permissions from your IAM backend on mount
  2. Permissions are cached in React state with TTL-based auto-refresh
  3. Guard components read permissions from context and conditionally render children
  4. 2FA/OAuth2/password reset hooks call the corresponding backend endpoints
  5. No access logic in your components — guards handle everything declaratively

Design Principles

  • Server is the source of truth — frontend never determines access, only renders what the backend permits
  • Zero access logic in components — use guards, not if (role === "admin")
  • Three-tier permissions — feature-level, action-level, field-level
  • DENY wins — if any role denies access, it's denied regardless of other roles
  • Implicit deny — no permission = no access
  • Components accept callbacks — 2FA and password reset components are decoupled from transport

Backend

This library works with the IAM Spring Boot Starter:

implementation("dev.mpofusindie:iam-spring-boot-starter:1.2.0")

The backend provides:

  • JWT authentication + OAuth2/OIDC (Google, Microsoft, any OIDC provider)
  • TOTP two-factor authentication with backup codes
  • Permission resolution with three-tier access control
  • Password reset with session invalidation
  • Multi-tenant support (JWT, header, subdomain resolution)
  • Management APIs for users, roles, groups, resources, permissions, OAuth2 providers
  • Audit logging with export and retention
  • Rate limiting (in-memory or Redis)

Troubleshooting

Blank page after login

IAMProvider calls GET /me/permissions on mount. If the request fails, no permissions are loaded and guard components render nothing. Check:

  • Is the JWT token valid and not expired? Look for 401 errors in the browser console.
  • Is apiUrl in IAMConfig pointing to the correct backend URL?
  • Is the backend running and reachable from the browser?

401 after token expiry

Access tokens expire after 15 minutes by default. After expiry, permission fetches return 401 and guards stop rendering. Use the refresh token flow (refreshMode in IAMConfig) to obtain new tokens automatically, or redirect the user to re-authenticate.

Guards not rendering children

If a guard component renders nothing even though the user should have access:

  • Check usePermissions().loading — guards return null while permissions are still loading.
  • Verify the resource prop matches the resource code configured in the backend exactly (case-sensitive).
  • For ActionGuard, verify the action prop matches the backend action code.
  • For FieldGuard, verify the field prop matches the backend field name.

OAuth2 callback blank page

React StrictMode double-mounts components in development, which can cause the OAuth2 callback to fire twice. Ensure your onSuccess handler in OAuth2Callback is idempotent — exchanging the same authorization code twice will fail on the second attempt.

CORS errors

If the browser console shows CORS errors when calling the IAM backend, the backend must include your frontend origin in its allowed origins configuration:

iam:
  security:
    cors-allowed-origins:
      - http://localhost:3000
      - https://your-frontend-domain.com

License

MIT