@bayonai/firebase-auth
v0.2.1
Published
Reusable Firebase authentication actions, React provider, MUI login surfaces, and passwordless email Functions.
Maintainers
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 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.
Install
pnpm add @bayonai/firebase-authPeer 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/styledApps 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,
},
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",
},
callFunction: async (name, payload) => {
const callable = httpsCallable(functions, name);
const result = await callable(payload);
return result.data;
},
});Actions include Google popup/redirect fallback, email/password sign-in, optional email/password account creation, optional verified-email enforcement, passwordless code/link completion, sign-out, and shared auth error formatting.
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,
createSendEmailLoginCodeFunction,
createSendPasswordResetEmailFunction,
type AuthEmailSender,
} from "@bayonai/firebase-auth/functions";
const db = getFirestore();
const auth = getAuth();
const emailSender: AuthEmailSender = {
async send(request) {
await sendEmailWithYourProvider({
to: request.to,
templateId: request.templateId,
variables: request.variables,
});
return { skipped: false };
},
};
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);
},
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);
},
templateId: "password_reset",
},
);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().
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.
- 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 --checkconsumer: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 whoamiBefore 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 publicAfter publish, verify the registry entry:
npm view @bayonai/firebase-auth name version dist.tarball time --jsonConsumers 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.
