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

@beamarco/auth-sdk

v0.1.23

Published

Beamar Auth SDK - Embed authentication in your React apps with Beamar Auth

Readme

@beamarco/auth-sdk

Embed authentication in your React apps with Beamar Auth. Works with the Beamar auth-service backend.

Installation

npm install @beamarco/auth-sdk

Quick Start

1. Wrap your app with BeamarAuthProvider

import { BeamarAuthProvider } from '@beamarco/auth-sdk'

const config = {
  apiUrl: 'https://auth.creztu.com',  // or your auth-service URL
  appName: 'my-app',                   // e.g. GOMEDI, developers-portal
  // googleClientId: optional — only if you use your own client-side Google button (see "Google auth options" below)
}

function App() {
  return (
    <BeamarAuthProvider config={config}>
      <YourApp />
    </BeamarAuthProvider>
  )
}

2. Use SignedIn / SignedOut for conditional rendering

import { SignedIn, SignedOut, SignIn, SignUp } from '@beamarco/auth-sdk'

function App() {
  return (
    <>
      <SignedIn>
        <Dashboard />
      </SignedIn>
      <SignedOut>
        <SignIn signUpUrl="/sign-up" />
      </SignedOut>
    </>
  )
}

3. Add routes (e.g. with React Router)

import { Routes, Route, Navigate } from 'react-router-dom'
import {
  BeamarAuthProvider,
  SignIn,
  SignUp,
  SignedIn,
  SignedOut,
  useAuth,
} from '@beamarco/auth-sdk'

function ProtectedRoute({ children }) {
  const { isLoaded, isSignedIn } = useAuth()
  if (!isLoaded) return <Spinner />
  if (!isSignedIn) return <Navigate to="/sign-in" replace />
  return children
}

function AuthRoute({ children }) {
  const { isLoaded, isSignedIn } = useAuth()
  if (!isLoaded) return <Spinner />
  if (isSignedIn) return <Navigate to="/" replace />
  return children
}

function App() {
  return (
    <BeamarAuthProvider config={config}>
      <Routes>
        <Route path="/" element={
          <ProtectedRoute><Home /></ProtectedRoute>
        } />
        <Route path="/sign-in" element={
          <AuthRoute><SignIn /></AuthRoute>
        } />
        <Route path="/sign-up" element={
          <AuthRoute><SignUp /></AuthRoute>
        } />
      </Routes>
    </BeamarAuthProvider>
  )
}

API

Components

| Component | Description | |-----------|-------------| | BeamarAuthProvider | Wrap your app; provides auth context | | SignIn | Email/password + Google sign-in form (Google uses redirect flow by default) | | SignUp | Email/password + Google sign-up form (Google uses redirect flow by default) | | SignedIn | Renders children only when signed in | | SignedOut | Renders children only when signed out | | SignInButton | Link/button to sign-in page | | SignUpButton | Link/button to sign-up page | | UserButton | User avatar/menu with sign out | | ProtectedRoute | Redirects to sign-in when not authenticated (fallbackRedirectUrl, loading props) | | TenantSelector | Full-page organization picker (same-domain or popup for cross-domain; see Tenant selection) | | OrgSwitcher | Compact dropdown for header/sidebar to switch organizations | | TenantGuard | Blocks children until a tenant is selected; shows TenantSelector if none | | TenantSelectCallback | Minimal callback page for popup flow; route at e.g. /auth/tenant-selected | | HostedTenantSelectRedirect | Redirects to auth-service hosted tenant selection (full redirect, cross-domain) |

Hooks

| Hook | Description | |------|-------------| | useAuth() / useBeamarAuth() | Full auth context: signIn, signOut, signInWithGoogle, signUpWithGoogle, signInWithMicrosoft, signUpWithMicrosoft, getGoogleOAuthRedirectUrl, getMicrosoftOAuthRedirectUrl, getToken, validateEmail, user, isLoaded, isSignedIn, apiUrl, appName; tenant: listTenants, getCurrentTenant, selectTenant, createTenant; org members: listTenantMembers, inviteTenantMember, updateTenantMemberRole, removeTenantMember, requestTenantMemberPasswordReset | | useUser() | Current user and loading state |

Note: useBeamarAuth is an alias for useAuth. AuthContext is exported for advanced usage (e.g. custom hooks).

validateEmail(loginId) checks if an email is already registered (e.g. for sign-up "email exists" checks).

getToken() returns a short-lived Bearer JWT for calling downstream services (e.g. screening-service). Only available for system-admin sessions; returns null otherwise. See Calling backend services below.

Component props

| Component | Key props | |-----------|-----------| | SignIn | afterSignInUrl, showGoogle, showMicrosoft, showSignUp, signUpUrl, forgotPasswordUrl, onSuccess, styles, children (render prop) | | SignUp | afterSignUpUrl, showGoogle, showMicrosoft, signInUrl, onSuccess, styles, children (render prop) | | SignInButton / SignUpButton | children, signInUrl/signUpUrl, fallbackRedirectUrl, style, className | | UserButton | children, fallback, style, className | | ProtectedRoute | fallbackRedirectUrl, loading | | OrgSwitcher | usePopupOpener, selectionCallbackPath, showCreate, onSwitch, onError | | TenantSelector | usePopupOpener, selectionCallbackPath, onSelected | | TenantGuard | usePopupOpener, selectionCallbackPath, onSelected | | HostedTenantSelectRedirect | redirectPath, fallback |

Render props: SignIn and SignUp accept a children function for fully custom layouts:

<SignIn>
  {({ signIn, signInWithGoogle, error, isLoading }) => (
    <YourCustomForm
      onEmailSubmit={signIn}
      onGoogleClick={signInWithGoogle}
      error={error}
      loading={isLoading}
    />
  )}
</SignIn>

Google auth – redirect helpers

| Function | Description | |----------|-------------| | getGoogleAuthUrl(options) | Build URL to hosted /sign-in page (email+password form + Google button) | | redirectToGoogleSignIn(options) | Redirect to hosted sign-in page | | redirectToGoogleSignUp(options) | Redirect to hosted sign-up page |

Two different redirect flows:

  • getGoogleAuthUrl / redirectToGoogleSignIn → auth-service /sign-in (hosted page with full form + Google). Best for custom pages; no Google setup needed.
  • getGoogleOAuthRedirectUrl(redirectUri) (from useAuth()) → auth-service /auth/google (two-step OAuth: redirect to Google, callback, establish). Google-only flow; no hosted page. Use when you want a "Sign in with Google" link that goes directly to OAuth.

Microsoft auth – redirect helpers

| Function | Description | |----------|-------------| | getMicrosoftAuthUrl(options) | Build URL to start Microsoft Entra ID OAuth (/auth/microsoft) | | redirectToMicrosoftSignIn(options) | Redirect browser to Microsoft OAuth |

Config

interface BeamarAuthConfig {
  apiUrl: string          // auth-service base URL
  appName: string         // application name (multi-tenant)
  googleClientId?: string // only for Option B (your own client-side Google button)
  parentUrl?: string     // base URL for password reset emails (e.g. your app origin). Auth-service links back here.
}

BeamarAuthProvider also supports publishableKey (e.g. beamar_live_developers-portal) instead of config; apiUrl is then taken from VITE_AUTH_SERVICE_URL.

Google auth: two options

You can add Google sign-in in two ways:

Option A: Redirect to hosted auth (recommended, no Google setup)

No Google Cloud Console setup needed. The <SignIn> and <SignUp> components use this by default. Their "Sign in with Google" button redirects to the auth-service's hosted page, where the Google button runs on a domain already authorized in Google. No "authorized JavaScript origins" errors.

For custom pages, use the redirect helpers:

import { redirectToGoogleSignIn, getGoogleAuthUrl } from '@beamarco/auth-sdk'

// Option 1: Button with redirect
function CustomLoginPage() {
  return (
    <button
      onClick={() => redirectToGoogleSignIn({
        apiUrl: 'https://auth.s.beamar.co',
        appName: 'my-app',
        redirectUri: '/dashboard',  // where to land after auth
      })}
    >
      Sign in with Google
    </button>
  )
}

// Option 2: Plain link (no JS needed for navigation)
function CustomLoginPage() {
  const googleUrl = getGoogleAuthUrl({
    apiUrl: 'https://auth.s.beamar.co',
    appName: 'my-app',
    redirectUri: '/dashboard',
    mode: 'signin',  // or 'signup'
  })
  return <a href={googleUrl}>Sign in with Google</a>
}

Flow: your button/link → auth-service /sign-in (hosted page with Google button) → user signs in with Google → redirect back to your redirectUri with session cookie set. Your app can then use BeamarAuthProvider and useUser() to read the session.

Option B: Your own Google client (client-side button)

If you prefer to embed the Google button directly in your app (e.g. with @react-oauth/google), you can:

  1. Add your app domain to Authorized JavaScript origins in Google Cloud Console
  2. Add googleClientId to your config
  3. Use your Google client to get the credential, then call signInWithGoogle({ credential, clientId }) or signUpWithGoogle({ credential, clientId }) from useAuth()
import { useAuth } from '@beamarco/auth-sdk'
import { GoogleOAuthProvider, GoogleLogin } from '@react-oauth/google'

function CustomGoogleButton() {
  const { signInWithGoogle } = useAuth()
  return (
    <GoogleOAuthProvider clientId="your-client-id.apps.googleusercontent.com">
      <GoogleLogin
        onSuccess={(res) => {
          if (res?.credential && res?.clientId) {
            signInWithGoogle({ credential: res.credential, clientId: res.clientId })
          }
        }}
        onError={() => {}}
      />
    </GoogleOAuthProvider>
  )
}

Microsoft Entra ID OAuth

Configure auth-service with MICROSOFT_CLIENT_ID, MICROSOFT_CLIENT_SECRET, and optional MICROSOFT_TENANT_ID (default common). In Azure Entra, add redirect URI {AUTH_CENTRAL_CALLBACK_URL}/auth/microsoft/callback (same base as Google’s central callback).

Redirect flow (recommended): use getMicrosoftOAuthRedirectUrl from useAuth(), or getMicrosoftAuthUrl / redirectToMicrosoftSignIn from the SDK. Enable <SignIn showMicrosoft /> and <SignUp showMicrosoft /> to show buttons. The hosted /sign-in page also shows “Sign in with Microsoft” when Microsoft env is set.

Client-side MSAL: obtain an ID token, then call signInWithMicrosoft({ tokenId }) or signUpWithMicrosoft({ tokenId }) from useAuth().

Calling backend services

For apps that need to call Beamar backend APIs (e.g. screening-service) with user context, use getToken():

import { useAuth } from '@beamarco/auth-sdk'

function ScreeningDashboard() {
  const { getToken } = useAuth()

  const fetchData = async () => {
    const token = await getToken()
    if (!token) throw new Error('Not authenticated')
    const res = await fetch('https://screening.example.com/api/lists', {
      headers: { Authorization: `Bearer ${token}` },
    })
    // ...
  }
}
  • System-admin only: getToken() returns a JWT only for system-admin sessions; regular app users get null.
  • Backend verification: Services verify the JWT using your app's JWKS URL. Retrieve the JWKS URL from the developers portal when viewing your auth application.
  • Short-lived: Tokens expire in a few minutes; call getToken() when needed rather than caching.

Tenant / Organization selection

Multi-tenant apps require the user to pick an organization before accessing data. The SDK provides components for same-domain and cross-domain flows.

Same domain (default)

When your app and auth-service share a domain (e.g. app.creztu.com and auth.creztu.com), tenant selection uses in-app API calls.

OrgSwitcher – compact dropdown for header/sidebar:

import { OrgSwitcher } from '@beamarco/auth-sdk'

// In your layout or header
<OrgSwitcher
  onSwitch={() => refetchData()}
  onError={(msg) => toast.error(msg)}
/>

TenantSelector – full-page organization picker:

import { TenantSelector } from '@beamarco/auth-sdk'

<TenantSelector
  onSelected={() => navigate('/dashboard')}
/>

TenantGuard – blocks rendering until a tenant is selected; shows TenantSelector if none:

import { TenantGuard } from '@beamarco/auth-sdk'

<TenantGuard onSelected={() => navigate('/dashboard')}>
  <Dashboard />
</TenantGuard>

Cross-domain: popup opener (no reload)

When your app and auth-service are on different domains, cookie-based selection can fail due to third-party cookie rules. Use the popup opener flow so selection happens on the auth domain (first-party cookies).

  1. Add the callback route (e.g. /auth/tenant-selected):
import { TenantSelectCallback } from '@beamarco/auth-sdk'

// In your router
<Route path="/auth/tenant-selected" element={<TenantSelectCallback />} />
  1. Enable popup mode with usePopupOpener:
// OrgSwitcher in header
<OrgSwitcher
  usePopupOpener
  selectionCallbackPath="/auth/tenant-selected"
  onSwitch={() => refetch()}
/>

// TenantSelector (full page)
<TenantSelector
  usePopupOpener
  selectionCallbackPath="/auth/tenant-selected"
  onSelected={() => navigate('/dashboard')}
/>

// TenantGuard
<TenantGuard
  usePopupOpener
  selectionCallbackPath="/auth/tenant-selected"
  onSelected={() => navigate('/dashboard')}
>
  <Dashboard />
</TenantGuard>

Flow: user picks an org → popup opens → auth-service sets the cookie → redirects to your callback → callback posts a message and closes → parent updates without reload.

Ensure /auth/tenant-selected (or your chosen path) is allowed in your app’s redirectUris in the developers portal.

Cross-domain: hosted page (full redirect)

For full redirect without popup, use HostedTenantSelectRedirect or redirectToTenantSelect:

import {
  HostedTenantSelectRedirect,
  redirectToTenantSelect,
  getSelectTenantUrl,
} from '@beamarco/auth-sdk'

// Redirect component (e.g. in TenantGuard fallback)
<HostedTenantSelectRedirect
  redirectPath="/dashboard"
  fallback={<Spinner />}
/>

// Or imperative
redirectToTenantSelect({
  apiUrl,
  appName,
  redirectUri: '/dashboard',
})

// Or as link
<a href={getSelectTenantUrl({ apiUrl, appName, redirectUri: '/dashboard' })}>
  Select organization
</a>

The user lands on the auth-service hosted page, selects an org, and is redirected back to your app. No popup; page reload when they return.

Tenant selection helpers

| Function | Description | |----------|-------------| | getSelectTenantUrl(options) | Build URL to auth-service hosted select-tenant page | | redirectToTenantSelect(options) | Redirect browser to hosted tenant selection | | getSelectTenantAndRedirectUrl(options) | Build URL for popup flow (internal use; components call this when usePopupOpener is true) |

Tenant selector props

| Component | Prop | Default | Description | |----------------|-----------------------|-------------------------|------------------------------------------------------------------| | OrgSwitcher | usePopupOpener | false | Use popup for cross-domain selection | | OrgSwitcher | selectionCallbackPath| '/auth/tenant-selected' | Callback path when usePopupOpener is true | | OrgSwitcher | showCreate | true | Show "Create new organization" in dropdown | | TenantSelector | usePopupOpener | false | Same as OrgSwitcher | | TenantSelector | selectionCallbackPath| '/auth/tenant-selected' | Same as OrgSwitcher | | TenantGuard | usePopupOpener | false | Same as OrgSwitcher | | TenantGuard | selectionCallbackPath| '/auth/tenant-selected' | Same as OrgSwitcher |

Tenant selection helpers

| Function | Description | |----------|-------------| | getSelectTenantUrl(options) | Build URL to auth-service hosted select-tenant page | | redirectToTenantSelect(options) | Redirect to hosted select-tenant page | | getSelectTenantAndRedirectUrl(options) | Build URL for popup flow (/tenants/select?ti=…&redirect_uri=…); used internally when usePopupOpener is true |

Hooks for tenant operations

From useBeamarAuth():

  • listTenants() – list orgs the user belongs to
  • getCurrentTenant() – currently selected org
  • selectTenant(tenantId) – switch org (in-app API; same-domain only)
  • createTenant(name) – create and select a new org

Organization members (team) — session + X-Beamar-App: listTenantMembers(tenantId?), inviteTenantMember({ email, role?, tenantId? }), updateTenantMemberRole({ userId, role, tenantId? }), removeTenantMember({ userId, tenantId? }), requestTenantMemberPasswordReset({ userId, tenantId?, parentUrl? }). Omit tenantId or pass 'current' for the tenant in the session. See auth-service docs/openapi-tenant-membership.yaml. Errors expose AuthError.code (e.g. INSUFFICIENT_PRIVILEGE, LAST_ADMIN).

After getSession(), user.tenantRole reflects the role in the selected tenant (from /user/preference). For roles across all orgs, use listTenants().

Tenant selection helpers

| Function | Description | |----------|-------------| | getSelectTenantUrl(options) | Build URL to auth-service hosted select-tenant page | | redirectToTenantSelect(options) | Redirect browser to hosted select-tenant page | | getSelectTenantAndRedirectUrl(options) | Build URL for popup flow (GET /tenants/select with redirect_uri); used internally when usePopupOpener is true |

For custom flows, you can use getSelectTenantAndRedirectUrl({ apiUrl, appName, tenantId, redirectUri }) to build the popup redirect URL yourself.

Configuring redirect URIs

When using the popup flow (usePopupOpener), ensure your callback path (e.g. https://your-app.com/auth/tenant-selected) is added to your application’s redirect URIs in the developers portal. The auth-service validates redirect URIs before redirecting back to your app.


Password reset

The auth-service supports email-based password reset. Use forgotPasswordUrl on SignIn to link to your custom "Forgot password?" page:

<SignIn forgotPasswordUrl="/forgot-password" />

Your forgot-password page can call the auth-service to request a reset email. For direct API access without the Provider, use BeamarAuthClient:

import { BeamarAuthClient } from '@beamarco/auth-sdk'

const client = new BeamarAuthClient({ apiUrl, appName, parentUrl })
await client.requestPasswordReset(email)
// User receives email with link. Your app handles the link (e.g. /reset-password?key=xxx)
// then: await client.updatePassword(key, newPassword)

BeamarAuthClient (low-level)

For non-React usage or when you need direct API access:

import { BeamarAuthClient } from '@beamarco/auth-sdk'

const client = new BeamarAuthClient({
  apiUrl: 'https://auth.s.beamar.co',
  appName: 'my-app',
  parentUrl: 'https://myapp.com',  // optional, for password reset
})

// Methods: login, register, logout, getSession, getToken, validateEmail,
// loginWithGoogle, registerWithGoogle, requestPasswordReset, updatePassword,
// listTenants, getCurrentTenant, selectTenant, createTenant,
// listTenantMembers, inviteTenantMember, updateTenantMemberRole, removeTenantMember, requestTenantMemberPasswordReset

All requests use credentials: 'include' for cookie-based sessions.

Error handling

import { AuthError } from '@beamarco/auth-sdk'

try {
  await signIn({ email, password })
} catch (err) {
  if (err instanceof AuthError) {
    console.error(err.message, err.statusCode, err.code)
  }
}

Types

interface User {
  id: string
  loginId: string
  displayName?: string
  imageUrl?: string
  cellphone?: string
  tenants?: TenantMember[]
}

interface TenantMember {
  tenant: { id: string; name?: string }
  userRole?: string
}

interface LoginCredentials { email: string; password: string }
interface RegisterCredentials { email: string; password: string }
interface GoogleCredential { credential: string; clientId: string }

CORS & Cookies

The auth-service uses httpOnly cookies for sessions. Ensure:

  1. Same origin or CORS with credentials: Your frontend and auth-service must allow credentials: 'include'.
  2. auth-service CORS: Set APP_CORS env var to include your frontend origin(s).
  3. Cookie domain: In production, auth-service may set domain for cross-subdomain cookies (e.g. .creztu.com).

Developers Portal & Creztu

To protect developers-portal or embed auth in the Creztu portal:

// developers-portal - Beamar Auth
import { BeamarAuthProvider, SignIn, SignedIn, SignedOut, UserButton } from '@beamarco/auth-sdk'

const config = {
  apiUrl: process.env.VITE_AUTH_API_URL,
  appName: 'developers-portal',
  // googleClientId optional — SignIn uses redirect flow by default
}

<BeamarAuthProvider config={config}>
  <SignedIn>
    <UserButton />
    <MainContent />
  </SignedIn>
  <SignedOut>
    <SignIn />
  </SignedOut>
</BeamarAuthProvider>