central-auth-sdk
v1.0.7
Published
Vanilla JS sign-up and login flow SDK — embeddable auth UI with configurable methods
Downloads
375
Maintainers
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 publishUse
npm publish --access publicif the package name is scoped (e.g.@your-org/central-auth-sdk).Integrators then:
npm install central-auth-sdkimport { 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 + PasswordmobilePassword— Mobile + PasswordemailOtp— Email + OTPmobileOtp— Mobile + OTPsocial.google/social.microsoft— Social loginemailFrs— 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:
onSignupComplete(payload)— Pass this callback when starting signup. The SDK calls it once when signup finishes, with a singlepayloadobject 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.
instance.getState()— At any time (including on the success screen), the parent can callgetState()to read current flow data. After completion, state also includessignupResult(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:
onLoginComplete(payload)— Pass this callback when starting login. The SDK calls it once when login finishes, with a singlepayloadobject 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)
instance.getState()— After completion, state includesloginResult(the raw final API response).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 referenceArchitecture
- 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.mdAPI 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).
