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

central-auth-sdk

v1.0.7

Published

Vanilla JS sign-up and login flow SDK — embeddable auth UI with configurable methods

Downloads

375

Readme

Central Auth Welcome Flow SDK

Vanilla JavaScript signup and login flows — embeddable into any web application. No React, Angular, or Vue.

Integrators: See INTEGRATION_GUIDE.md for how to pull the SDK and use all functionalities (install, config, signup/login, callbacks, tokens, and a full example).

Distributing the SDK

Simplest options:

1. npm (recommended)

Publish the sdk folder as its own package so integrators can install it with one command.

  • Log in to npm (one-time): npm login (you need an account at npmjs.com).

  • From the repo root, go to the SDK folder and publish:

    cd sdk
    npm publish

    Use npm publish --access public if the package name is scoped (e.g. @your-org/central-auth-sdk).

  • Integrators then:

    npm install central-auth-sdk
    import { startSignup, startLogin } from 'central-auth-sdk';

    They also need to load the CSS (e.g. in their app entry or HTML):

    import 'central-auth-sdk/styles.css';

    or

    <link rel="stylesheet" href="./node_modules/central-auth-sdk/styles.css" />

Pros: Versioning, semver, one install command, works with any bundler.
Cons: Integrators need Node/npm (or equivalent).

2. Copy / embed (no build)

Ship the SDK as source in a zip, Git repo, or copy the sdk folder into the parent app. The parent app points at the folder (e.g. Vite alias or relative path).

  • Example (parent app has sdk/ at repo root):
    <link rel="stylesheet" href="/sdk/styles.css" />
    <script type="module">
      import { startLogin } from '/sdk/index.js';
      startLogin({ container: '#auth', env: 'dev', loginMethods: { emailPassword: true } });
    </script>

Pros: No publish step, no npm; works with any dev server that serves the sdk folder.
Cons: No versioning via registry; updates are manual (replace files or pull from Git).

3. CDN / single-file bundle (optional)

For environments without a bundler, you can add a build step that bundles the SDK into a single JS file (and keep styles.css separate). Then host it (or publish to npm and use unpkg/jsDelivr). This requires a small Vite/Rollup config that builds sdk/index.js into e.g. dist/central-auth-sdk.js. Many teams skip this and use option 1 or 2.


Public API (recommended)

The SDK exposes callable functions so the host application can initialize and trigger Sign-Up or Login programmatically with static configuration parameters.

initializeAuth(config)

Call once (e.g. at app load) to set default configuration. Optional; you can pass all config when calling startSignup / startLogin instead.

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | env | string | 'local' | Environment: 'local' | 'dev' | 'staging' | 'prod'. SDK uses the predefined API URL for that env. | | appIdentifier | string | 'control-center' | App identifier for OAuth and custom login | | defaultContainer | string | HTMLElement | — | Default container for rendering (can override in startSignup / startLogin) | | loginMethods | object | — | Default enabled login methods (see Login config below) | | frsAsSecondFactor | boolean | false | Default: require face verification after primary auth | | enableFaceRegistration | boolean | true | Whether sign-up flow includes face registration step |

Returns: { startSignup, startLogin, getConfig }

startSignup(config)

Starts the Sign-Up flow in the given container. Configuration is static (passed when triggering, not collected from the user).

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | container | string | HTMLElement | yes* | DOM selector or element where the SDK renders (*or set defaultContainer in initializeAuth) | | env | string | no | Environment: 'local' | 'dev' | 'staging' | 'prod' (default from init or 'local') | | appIdentifier | string | no | Override app identifier | | enableFaceRegistration | boolean | no | Include face registration step (default from init or true) |

Returns: { unmount, getState, getFlow, getCurrentStep } or null if container invalid.

startLogin(config)

Starts the Login flow in the given container with configurable login methods.

| Parameter | Type | Required | Description | |-----------|------|----------|-------------| | container | string | HTMLElement | yes* | DOM selector or element where the SDK renders | | env | string | no | Environment: 'local' | 'dev' | 'staging' | 'prod' (default from init or 'local') | | appIdentifier | string | no | Override app identifier | | loginMethods | object | no | Which login methods are enabled (see below) | | frsAsSecondFactor | boolean | no | Require face verification after primary auth | | onSignUp | function | no | Callback when user clicks “Sign up” (e.g. switch to signup) |

Enabled login methods (loginMethods):

  • emailPassword — Email + Password
  • mobilePassword — Mobile + Password
  • emailOtp — Email + OTP
  • mobileOtp — Mobile + OTP
  • social.google / social.microsoft — Social login
  • emailFrs — Email + Face (FRS only, no password/OTP)

Returns: { unmount, getState, getFlow, getCurrentStep } or null if container invalid.

Theming (optional)

Pass a theme object to match the SDK to your app's look. All properties are optional — omit any to keep the SDK default.

startSignup({
  container: '#auth-container',
  env: 'dev',
  theme: {
    primaryColor: '#2563EB',       // buttons, links, accent
    backgroundColor: '#EFF6FF',    // page background
    backgroundImage: 'https://…',  // optional full-bleed image
    cardColor: '#FFFFFF',          // card panel
    textColor: '#1A1714',          // primary text
    fontFamily: '"DM Sans", sans-serif',
    mode: 'auto',                  // 'light' | 'dark' | 'auto'
  },
});

Built-in presets: import { THEME_PRESETS } from 'central-auth-sdk' — keys: default, dark, ocean, forest, purple, rose, midnight.

See INTEGRATION_GUIDE.md § 5.1 for full details.

Example: initialize once, then trigger flows

<div id="auth-container"></div>
<link rel="stylesheet" href="/path/to/sdk/styles.css" />
<script type="module">
  import { initializeAuth, startSignup, startLogin } from '/path/to/sdk/index.js';

  const auth = initializeAuth({
    env: 'dev',
    appIdentifier: 'my-app',
    defaultContainer: '#auth-container',
    loginMethods: {
      emailPassword: true,
      emailOtp: true,
      social: { google: true, microsoft: true },
      emailFrs: false,
    },
    frsAsSecondFactor: true,
  });

  let currentInstance = null;

  function showSignup() {
    if (currentInstance) currentInstance.unmount();
    currentInstance = auth.startSignup({});  // uses defaultContainer + init config
  }

  function showLogin() {
    if (currentInstance) currentInstance.unmount();
    currentInstance = auth.startLogin({
      onSignUp: showSignup,
    });
  }

  showLogin();  // or showSignup()
</script>

Example: trigger without initializeAuth

You can pass all configuration when starting a flow (no need to call initializeAuth):

import { startSignup, startLogin } from '/path/to/sdk/index.js';

const signupInstance = startSignup({
  container: '#auth-container',
  env: 'dev',
  appIdentifier: 'my-app',
});

const loginInstance = startLogin({
  container: '#auth-container',
  env: 'dev',
  appIdentifier: 'my-app',
  loginMethods: {
    emailPassword: true,
    mobilePassword: true,
    emailOtp: true,
    mobileOtp: true,
    social: { google: true, microsoft: true },
    emailFrs: true,
  },
  frsAsSecondFactor: false,
  onSignUp() {
    loginInstance.unmount();
    startSignup({ container: '#auth-container', env: 'dev' });
  },
});

Sending signup result (token + details) back to the parent app

When signup completes (after the final step, e.g. face registration), the SDK gives the parent app the result in two ways:

  1. onSignupComplete(payload) — Pass this callback when starting signup. The SDK calls it once when signup finishes, with a single payload object that includes:

    • email, mobile, userId (from the flow)
    • Any fields returned by the final API call (e.g. access_token, refresh_token, user_id) — the backend can return whatever it needs here.
  2. instance.getState() — At any time (including on the success screen), the parent can call getState() to read current flow data. After completion, state also includes signupResult (the raw final API response).

Example:

const instance = startSignup({
  container: '#auth-container',
  env: 'dev',
  appIdentifier: 'my-app',
  onSignupComplete(payload) {
    // payload.email, payload.mobile, payload.userId
    // payload.access_token, payload.refresh_token (if your API returns them)
    console.log('Signup complete', payload);
    myApp.saveSession(payload.access_token);
    instance.unmount();
    myApp.redirectToDashboard();
  },
  onContinue() {
    // User clicked "Go to Dashboard" / "Back to Home" on the success screen
    instance.unmount();
    myApp.redirectToDashboard();
  },
});

The backend should return token (and any other session data) in the final signup API response (e.g. POST /signup/fr/enroll or the social FR enroll endpoint). The SDK forwards that response into payload and into getState().signupResult.

Sending login result (token + details) back to the parent app

When login completes (after the final successful API call — password, OTP, or FRS), the SDK gives the parent app the result in the same way as signup:

  1. onLoginComplete(payload) — Pass this callback when starting login. The SDK calls it once when login finishes, with a single payload object that includes:

    • identifier (email or mobile used to sign in)
    • Any fields returned by the final API call (e.g. access_token, refresh_token, user_id)
  2. instance.getState() — After completion, state includes loginResult (the raw final API response).

  3. onContinue() — Called when the user clicks Continue on the login success screen (e.g. to unmount and redirect).

Example:

const instance = startLogin({
  container: '#auth-container',
  env: 'dev',
  appIdentifier: 'my-app',
  loginMethods: { emailPassword: true },
  onLoginComplete(payload) {
    // payload.identifier, payload.access_token, payload.refresh_token (if API returns them)
    myApp.saveSession(payload.access_token);
    instance.unmount();
    myApp.redirectToApp();
  },
  onContinue() {
    instance.unmount();
    myApp.redirectToApp();
  },
  onSignUp() { /* switch to signup */ },
});

The backend should return token (and any session data) in the final login API response (e.g. POST /login/custom, POST /otp/verify, POST /login/email/fr, or social FR enroll). The SDK forwards that response into payload and into getState().loginResult.

Instance API (returned by startSignup / startLogin)

instance.unmount()        // Remove the flow from DOM
instance.getState()      // Read form data (email, mobile, userId, signupResult / loginResult, etc.)
instance.getCurrentStep() // Current step name
instance.getFlow()       // FlowController reference

Architecture

  • UI layer (sdk/ui/) — Screens and layout, pure DOM
  • Core layer (sdk/core/) — Flow, state, events; ready for API integration
  • Separation of concerns — UI emits actions; core handles logic; APIs plug in later

Lower-level embedding (mount / mountLogin)

If you prefer not to use initializeAuth / startSignup / startLogin, you can use the same underlying functions:

1. Include styles and mount

<div id="signup-container"></div>
<link rel="stylesheet" href="/path/to/sdk/styles.css" />
<script type="module">
  import { mount } from '/path/to/sdk/index.js';
  const instance = mount('#signup-container');
</script>

2. Mount options

mount('#signup', {
  env: 'local',
  appIdentifier: 'control-center',       // for social OAuth
});

Entity is derived from email in the backend; no need to pass entity name/domain.

3. Login flow (lower-level)

import { mountLogin } from '/path/to/sdk/index.js';

const loginInstance = mountLogin('#login-container', {
  env: 'local',
  appIdentifier: 'control-center',
  loginMethods: { emailPassword: true, /* ... */ },
  frsAsSecondFactor: true,
  onSignUp() { /* switch to signup */ },
});

4. Integration with existing apps

  • Use any container selector or HTMLElement
  • No global pollution; all logic is scoped
  • Styles use wf- prefix to avoid conflicts

UI design rules

When adding or changing screens, follow DESIGN_RULES.md for tokens, typography, spacing, component patterns, and a new-screen checklist.

File structure

sdk/
├── core/
│   ├── api.js         # Central Auth API client (central_auth_collection.json)
│   ├── flow.js        # Step navigation, flow type (standard/social)
│   ├── state.js       # Form data
│   ├── login-config.js
│   ├── login-flow.js
│   ├── login-state.js
│   └── events.js      # Event bus (optional)
├── ui/
│   ├── layout.js
│   ├── components.js
│   ├── screens/
│   │   ├── (signup screens)
│   │   └── login/
│   │       ├── entry.js, identifier-email.js, identifier-mobile.js
│   │       ├── password.js, otp.js, frs.js, success.js
│   │       └── index.js
│   └── screens/index.js
├── index.js       # Main entry: initializeAuth, startSignup, startLogin, mount, mountLogin
├── auth.js        # Public API: initializeAuth, startSignup, startLogin
├── signup.js      # Sign-up flow: mount()
├── login.js       # Login flow: mountLogin()
├── styles.css
└── README.md

API integration

APIs from central_auth_collection.json are wired in core/api.js. See API_INTEGRATION.md for endpoint mapping, options (entityName, entityDomain), and response assumptions (user_id from email verify).