npm.io
1.0.7 • Published 2h ago

central-auth-sdk

Licence
MIT
Version
1.0.7
Deps
0
Size
183 kB
Vulns
0
Weekly
2

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:

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.


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).

Keywords