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

@bayonai/firebase-auth

v0.5.0

Published

Reusable Firebase authentication actions, React provider, MUI login surfaces, and passwordless email Functions.

Readme

@bayonai/firebase-auth

Reusable Firebase authentication primitives for BayonAI apps.

The package includes app-agnostic Firebase auth actions, a React auth provider, configurable MUI login surfaces, and Firebase Functions factories for server-owned registration and passwordless email code/link login. Each app still owns Firebase initialization, workspace bootstrap, routes, copy, theme, Firestore domain logic, and the email transport used by Functions.

Successfully completing a passwordless code or link marks an existing account's email verified: accepting an emailed credential proves control of its recipient address. Host apps that treat other emailed links as verification must attach their own recipient-bound proof in the email adapter and complete that proof before opening the original action. This ownership proof can be reusable while password reset and sign-in action credentials retain their separate security limits. Failed registration email delivery keeps the account and reports verificationEmailSent: false for a later resend.

Simplified Authentication UX

All package implementations should follow this contract:

Create account
  -> server creates the Firebase user
  -> server creates a custom token and attempts the branded verification email
  -> server returns the token and delivery status, preserving the account if mail fails
  -> client signs in immediately
  -> app is usable while email verification remains a soft account state

Returning password user
  -> password sign-in
  -> client enters the app whether or not emailVerified is true

Email action completion
  -> server proves mailbox control
  -> server marks the email verified when appropriate
  -> client signs in automatically when the action returns a custom token

Registration must not create a Firebase user in the browser and then depend on a second request to deliver verification. requireVerifiedEmail should remain false for this flow. Verification is an ownership signal for account state, not a forced second login. Hosts may change the copy, routes, and bootstrap destination, but should not change these sequencing or recovery guarantees.

Install

pnpm add @bayonai/firebase-auth

Peer dependencies are intentionally external so the host app controls runtime versions:

pnpm add firebase react react-dom @mui/material @mui/icons-material @emotion/react @emotion/styled

Apps that use the passwordless Functions factories also need compatible firebase-admin and firebase-functions versions in their Functions package.

Configure Login Methods

Use one method config as the source of truth for actions, provider setup, UI, and Functions options.

import {
  type FirebaseAuthUiConfig,
  buildFirebaseAuthMethodConfig,
} from "@bayonai/firebase-auth";

export const authMethods = buildFirebaseAuthMethodConfig({
  google: {
    enabled: true,
    preferRedirect: "ios-standalone",
  },
  emailPassword: {
    enabled: true,
    allowAccountCreation: true,
    requireVerifiedEmail: false,
    sendVerificationEmail: true,
  },
  passwordlessEmail: {
    enabled: false,
    deliveryModes: ["code", "link"],
    resendEnabled: true,
  },
});

export const authUiConfig: FirebaseAuthUiConfig = {
  appName: "Example App",
  introTitle: "Sign in",
  introDescription: "Use your account to continue.",
  redirectAfterAuthHref: "/tasks",
  disabledMethodsFallback: "Sign-in is temporarily unavailable.",
  methods: authMethods,
};

Defaults from buildFirebaseAuthMethodConfig:

| Method | Default | | ------------------------------------ | ------------------ | | google.enabled | true | | google.preferRedirect | "ios-standalone" | | emailPassword.enabled | true | | emailPassword.allowAccountCreation | true | | emailPassword.requireVerifiedEmail | false | | passwordlessEmail.enabled | false | | passwordlessEmail.deliveryModes | ["code", "link"] | | passwordlessEmail.resendEnabled | true |

Disabled methods are hidden by the MUI components. If an app calls a disabled action directly, it rejects with AuthMethodDisabledError.

Client Actions

Create actions in app code so the package can use the app's Firebase instance, callable transport, storage, and function names.

import { getAuth } from "firebase/auth";
import { getFunctions, httpsCallable } from "firebase/functions";
import { createFirebaseAuthActions } from "@bayonai/firebase-auth";
import { authMethods } from "./authConfig";

const functions = getFunctions();

export const authActions = createFirebaseAuthActions({
  appName: "Example App",
  getAuth,
  methods: authMethods,
  storage: typeof window === "undefined" ? undefined : window.localStorage,
  storageKey: "example.firebaseAuth.emailLoginAttempt",
  functionNames: {
    sendEmailLoginCode: "sendEmailLoginCode",
    completeEmailLoginCode: "completeEmailLoginCode",
  },
  serverFunctionNames: {
    registerEmailPassword: "registerEmailPassword",
  },
  callFunction: async (name, payload) => {
    const callable = httpsCallable(functions, name);
    const result = await callable(payload);
    return result.data;
  },
});

Actions include Google popup/redirect fallback, server-owned email/password registration, email/password sign-in, passwordless code/link completion, sign-out, and shared auth error formatting. A configured registerEmailPassword server function is the package path for account creation; the client-created fallback remains only for hosts that deliberately omit that server function and do not send verification from the package.

User-facing error contract

Authentication UI must display only package-owned recovery guidance. Firebase, identity-provider, callable, and SDK exception messages are diagnostic data and must be logged or retained as an error cause, never rendered directly. The shared formatGoogleAuthErrorMessage, formatEmailLoginErrorMessage, and formatPasswordAuthErrorMessage helpers enforce this fail-closed behavior, and the packaged MUI login panel invokes them directly for every authentication failure. Hosts cannot replace the panel's mediator through its actions prop.

Use FirebaseAuthUserError only for deliberate, user-safe guidance produced by application or package code. Unknown Error messages remain untrusted and are replaced with a stable fallback.

React Provider

The provider owns Firebase auth readiness, Google redirect result consumption, optional bootstrap caching, optional claim parsing, and app bootstrap callbacks.

import {
  FirebaseAuthProvider,
  useFirebaseAuth,
} from "@bayonai/firebase-auth/react";
import { getAuth } from "firebase/auth";
import { authActions } from "./authActions";
import { ensureUserWorkspace } from "./ensureUserWorkspace";

const defaultClaims = { admin: false };

export function AppAuthProvider({ children }: { children: React.ReactNode }) {
  return (
    <FirebaseAuthProvider
      actions={authActions}
      defaultClaims={defaultClaims}
      getAuth={getAuth}
      readClaims={(claims) => ({ admin: claims.admin === true })}
      bootstrapUser={async (user) => {
        const workspace = await ensureUserWorkspace(user);
        return { primaryEntityId: workspace.id };
      }}
    >
      {children}
    </FirebaseAuthProvider>
  );
}

export function CurrentUserEmail() {
  const auth = useFirebaseAuth<typeof defaultClaims>();

  return auth.user?.email ?? null;
}

Keep app-specific bootstrap behavior, workspace creation, authorization claims, and route decisions in the host app.

MUI Login UI

LoginView wraps LoginPanel with auth-status handling and redirect behavior. Both components render only enabled login methods.

import { LoginView } from "@bayonai/firebase-auth/mui";
import { useRouter } from "next/navigation";
import { useFirebaseAuth } from "@bayonai/firebase-auth/react";
import { authActions } from "./authActions";
import { authUiConfig } from "./authConfig";

export function LoginPage() {
  const router = useRouter();
  const auth = useFirebaseAuth();

  return (
    <LoginView
      actions={authActions}
      authStatus={auth.status}
      config={authUiConfig}
      replaceRoute={(href) => router.replace(href)}
      loadingLabel="Preparing your workspace..."
      labels={{
        googleButton: "Continue with Google",
        passwordSignInButton: "Sign in",
        passwordCreateButton: "Create account",
        sendCodeButton: "Send code",
        verifyCodeButton: "Verify code",
        resendCodeTooltip: "Send a new code",
      }}
    />
  );
}

Use LoginPanel directly when the app already owns the surrounding layout. The panel accepts sx, headerSlot, statusMessage, signedInPreparing, passwordlessCooldownSeconds, labels, and an optional toast adapter.

Passwordless Firebase Functions

The Functions export provides factories for apps that enable passwordless email. The app supplies Firestore, Admin Auth, email sender, template IDs, callable options, app URL, and delivery modes.

import { getAuth } from "firebase-admin/auth";
import { getFirestore } from "firebase-admin/firestore";
import {
  createCompleteEmailLoginCodeFunction,
  createFirestoreAuthRateLimiter,
  createRegisterEmailPasswordFunction,
  createSendEmailLoginCodeFunction,
  createSendPasswordResetEmailFunction,
  createSendEmailVerificationFunction,
  type AuthEmailSender,
} from "@bayonai/firebase-auth/functions";

const db = getFirestore();
const auth = getAuth();
const rateLimiter = createFirestoreAuthRateLimiter(db);

const emailSender: AuthEmailSender = {
  async send(request) {
    await sendEmailWithYourProvider({
      to: request.to,
      templateId: request.templateId,
      variables: request.variables,
    });

    return { skipped: false };
  },
};

export const registerEmailPassword = createRegisterEmailPasswordFunction(
  auth,
  emailSender,
  {
    appUrl: process.env.NEXT_PUBLIC_APP_URL,
    logger: console,
    onEvent: async (event) => {
      await recordAuthEvent(event);
    },
    rateLimiter,
    templateId: "email_verification",
    verificationPath: "/verify-email",
  },
);

export const sendEmailLoginCode = createSendEmailLoginCodeFunction(
  db,
  auth,
  emailSender,
  {
    appUrl: process.env.NEXT_PUBLIC_APP_URL,
    deliveryModes: ["code", "link"],
    logger: console,
    onEvent: async (event) => {
      await recordAuthEvent(event);
    },
    rateLimiter,
    securityLimits: {
      emailLoginTtlMs: 10 * 60 * 1000,
      resendCooldownMs: 5 * 60 * 1000,
      maxEmailRequestsPerRecipient: 3,
      maxCodeAttempts: 5,
    },
    signInPath: "/login",
    templateId: "email_login_code",
  },
);

export const completeEmailLoginCode = createCompleteEmailLoginCodeFunction(
  db,
  auth,
  {
    deliveryModes: ["code", "link"],
  },
);

export const sendPasswordResetEmail = createSendPasswordResetEmailFunction(
  auth,
  emailSender,
  {
    appUrl: process.env.NEXT_PUBLIC_APP_URL,
    logger: console,
    onEvent: async (event) => {
      await recordAuthEvent(event);
    },
    rateLimiter,
    templateId: "password_reset",
  },
);

export const sendEmailVerification = createSendEmailVerificationFunction(
  auth,
  emailSender,
  {
    appUrl: process.env.NEXT_PUBLIC_APP_URL,
    logger: console,
    onEvent: async (event) => {
      await recordAuthEvent(event);
    },
    rateLimiter,
    templateId: "email_verification",
    verificationPath: "/verify-email",
  },
);

Set deliveryModes to ["code"], ["link"], or ["code", "link"] to control what gets created and sent. Do not enable passwordless login in the app config until its Functions and email adapter are deployed.

Set signInPath when an app needs emailed links to target an app-owned route other than /login, such as a hosted mobile App Links path. The package keeps the attempt and token query parameters stable so existing completion handlers can continue using readEmailLoginLinkParams().

Set verificationPath when verification links should target an app-owned route other than /login. For public verification forms, set allowAnonymousEmailLookup: true and pass the submitted email in the callable payload. Unknown or already verified addresses return { sent: true } so the endpoint does not disclose account existence. Keep this option disabled when the callable is only used by authenticated users.

Registration and password-reset delivery require a server-owned rateLimiter. Anonymous verification requires one as well. The Bounded Functions adapters supply the Firestore-backed limiter automatically; other hosts should reuse one createFirestoreAuthRateLimiter(db) instance and keep its backing collection inaccessible to browser clients. Each public email flow enforces a recipient limit and, when Firebase exposes a requester address, a wider requester limit.

Functions Diagnostics

The Functions API exposes one app-owned auth email contract:

import type {
  AuthEmailSender,
  AuthPackageEvent,
  AuthPackageLogger,
} from "@bayonai/firebase-auth/functions";

Use AuthEmailSender for provider-specific delivery adapters. The package only creates auth links, login attempts, hashes, and typed delivery requests. Host apps own email providers, templates, sender identities, logs, retries, and operator alerts.

Use logger for operational diagnostics and onEvent for app-owned audit or metrics pipelines. Event payloads are intentionally safe: they can include event names, attempt IDs, reasons, booleans, and email domains, but never login codes, sign-in tokens, reset links, or full recipient emails.

securityLimits lets apps tune passwordless login defaults without forking the package:

resendCooldownMs is the rolling per-recipient window. The package permits up to maxEmailRequestsPerRecipient requests within that window; it is not a single-request cooldown.

| Limit | Default | | ------------------------------ | -------- | | emailLoginTtlMs | 600000 | | resendCooldownMs | 300000 | | maxEmailRequestsPerRecipient | 3 | | registrationWindowMs | 300000 | | maxRegistrationAttemptsPerIp | 3 | | maxCodeAttempts | 5 |

Package Boundary

This package owns reusable auth behavior:

  • Method config validation and disabled-method guards.
  • Firebase client auth actions.
  • Auth state/provider boot sequence.
  • Shared login UI behavior and messages.
  • Server-owned registration and passwordless email callable factories and request/result types.

Host apps own app-specific behavior:

  • Firebase app initialization and callable wiring.
  • Workspace/user bootstrap such as ensureUserWorkspace.
  • Routes, redirects, copy, theme, and page layout.
  • Firestore domain models and authorization semantics.
  • Email provider configuration, templates, and sender identity.

Release Checklist

From the Bounded repo root:

pnpm --filter @bayonai/firebase-auth build
pnpm --filter @bayonai/firebase-auth test
pnpm --filter @bayonai/firebase-auth lint
pnpm --filter @bayonai/firebase-auth pack:smoke
pnpm --filter @bayonai/firebase-auth consumer:smoke
pnpm lint
pnpm build
pnpm test
git diff --check

consumer:smoke installs the packed tarball into a temporary app and checks ESM, CommonJS, TypeScript, and subpath imports from the outside. Run it before publishing any version.

From packages/firebase-auth:

npm publish --dry-run --access public
npm view @bayonai/firebase-auth name version dist.tarball time --json
npm whoami

Before the first real publish, npm view should return E404 and npm whoami must succeed. If npm whoami returns E401, run npm login first.

Real publish command:

npm publish --access public

After publish, verify the registry entry:

npm view @bayonai/firebase-auth name version dist.tarball time --json

Consumers should stay on local file: or workspace dependencies until the npm package has been published and verified.

License

This package is proprietary commercial software. Installing, downloading, or accessing it does not grant a free license or any implied right to use, copy, modify, publish, distribute, sublicense, sell, or otherwise exploit the package. Use requires a separate written commercial license agreement with BayonAI that expressly grants those rights.

For licensing inquiries, contact BayonAI.

Error recovery copy

Errors describe a recovery action without instructing users to contact support. Keep network, sign-in, and service-availability guidance specific to the failure.

Error-copy contract: authored failures state the failed outcome without bare retry instructions. Known throttling waits, corrective steps and alternate sign-in methods remain available. Hosts own recovery controls and sanitization of legacy server messages; original errors and stable codes remain diagnostic.

Password and login presentation contract

Passwords are passed exactly as entered, including whitespace. Email and reset-code normalization are unchanged; existing provider password policies still apply. LoginPanel accepts initialEmailMethod="password" for direct password entry and passwordResetEnabled={false} to hide recovery when the host has no reset service. Disabled methods remain unavailable; defaults remain the code tab and visible reset control. Successful password sign-in clears/conceals the field. Visibility controls respect busy state and retain input focus on pointer activation. See the repository contract docs/contracts/firebase-auth-password-input.md.