# Central Auth SDK — Integration Guide

This guide explains how to **pull the SDK** and use **all SDK functionalities** in your application.

---

## 1. Pull / install the SDK

```bash
npm install central-auth-sdk
```

Use in your app (with a bundler such as Vite, Webpack, or Parcel):

```javascript
import { initializeAuth, startSignup, startLogin } from 'central-auth-sdk';
import 'central-auth-sdk/styles.css';
```

Or in HTML (if your tool resolves node_modules):

```html
<link rel="stylesheet" href="./node_modules/central-auth-sdk/styles.css" />
<script type="module">
  import { startSignup, startLogin } from 'central-auth-sdk';
  // ...
</script>
```

---

## 2. Minimal setup

You need:

1. A **container** element in the DOM where the SDK will render.
2. The **SDK CSS** loaded (so the UI looks correct).
3. A call to **`startSignup`** or **`startLogin`** with at least `container` and **`env`** (which backend to use: `local`, `dev`, `staging`, or `prod`). **`appIdentifier`** is optional; include it only if your backend expects it for OAuth or login APIs.

**Minimal signup example:**

```html
<div id="auth-container"></div>
<link rel="stylesheet" href="central-auth-sdk/styles.css" />
<script type="module">
  import { startSignup } from 'central-auth-sdk';

  const instance = startSignup({
    container: '#auth-container',
    env: 'dev',
    appIdentifier: 'your-app-id',
  });
</script>
```

**Minimal login example:**

```html
<div id="auth-container"></div>
<link rel="stylesheet" href="central-auth-sdk/styles.css" />
<script type="module">
  import { startLogin } from 'central-auth-sdk';

  const instance = startLogin({
    container: '#auth-container',
    env: 'dev',
    appIdentifier: 'your-app-id',
    loginMethods: { emailPassword: true },
  });
</script>
```

---

## 3. All SDK functions

| Function | Purpose |
|----------|--------|
| **`initializeAuth(config)`** | (Optional) Set default config once; `startSignup` / `startLogin` can override per call. |
| **`startSignup(config)`** | Run the sign-up flow in the given container. |
| **`startLogin(config)`** | Run the login flow in the given container. |

You can use **only** `startSignup` and `startLogin` and pass full config each time. Or call **`initializeAuth`** once and then call **`auth.startSignup({})`** / **`auth.startLogin({})`** so they use the stored defaults.

---

## 4. initializeAuth(config)

Call once (e.g. at app load) to set defaults. Returns `{ startSignup, startLogin, getConfig }`.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `env` | string | `'local'` | Environment: `'local'` \| `'dev'` \| `'staging'` \| `'prod'`. SDK uses the predefined API URL for that env. |
| `appIdentifier` | string | — | Optional. When provided, sent with OAuth and login-related API requests; omit to not send `app_identifier`. |
| `defaultContainer` | string \| HTMLElement | — | Default container; can override in `startSignup` / `startLogin` |
| `loginMethods` | object | — | Default login methods (see Login config) |
| `frsAsSecondFactor` | boolean | `false` | Default: require face verification after primary auth |
| `enableFaceRegistration` | boolean | `true` | Whether sign-up includes face registration step |

**Environments:** The SDK uses only `env` to choose the API base URL:

| `env`     | API base URL |
|-----------|----------------|
| `local`   | `http://localhost:8080` |
| `dev`     | `https://central-auth-dev.soham.ai/apis` |
| `staging` | `https://central-auth-staging.soham.ai/apis` |
| `prod`    | `https://central-auth.soham.ai/apis` |

**Example:**

```javascript
import { initializeAuth } from 'central-auth-sdk';

const auth = initializeAuth({
  env: 'dev',  // uses https://central-auth-dev.soham.ai/apis
  appIdentifier: 'my-app',
  defaultContainer: '#auth-container',
  loginMethods: {
    emailPassword: true,
    emailOtp: true,
    social: { google: true, microsoft: true },
  },
  frsAsSecondFactor: true,
});

// Later:
auth.startSignup({});
auth.startLogin({ onSignUp: () => showSignup() });
```

---

## 5. startSignup(config)

Starts the **sign-up flow** (email + name → verify → mobile → verify → password → face → success). The first screen collects first name, last name, and email.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `container` | string \| HTMLElement | yes* | Where to render (*or set `defaultContainer` in `initializeAuth`) |
| `env` | string | no | Environment: `'local'` \| `'dev'` \| `'staging'` \| `'prod'` (default from init or `'local'`) |
| `appIdentifier` | string | no | Optional. When provided, sent with relevant API requests; omit to not send. |
| `enableFaceRegistration` | boolean | no | Include face registration step (default from init or `true`) |
| **`onSignupComplete(payload)`** | function | no | Called **once** when signup completes. `payload`: `email`, `mobile`, `userId` + any fields from final API (e.g. `access_token`, `refresh_token`). |
| **`onContinue()`** | function | no | Called when user clicks **Continue to application** on the success screen. Use to unmount and redirect. |
| **`onSwitchToLogin()`** | function | no | Called when user clicks **Sign in** (e.g. “Already have an account? Sign in”). Use to unmount signup and start the login flow in the **same container** (e.g. login + FRS). |

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

**Example with callbacks (including switch to login):**

```javascript
const instance = startSignup({
  container: '#auth-container',
  env: 'dev',
  appIdentifier: 'my-app',
  onSignupComplete(payload) {
    console.log('Signup done', payload);
    saveToken(payload.access_token);
    instance.unmount();
    redirectToDashboard();
  },
  onContinue() {
    instance.unmount();
    redirectToDashboard();
  },
  onSwitchToLogin() {
    instance.unmount();
    startLogin({ container: '#auth-container', env: 'dev', appIdentifier: 'my-app', loginMethods: { emailFrs: true }, onContinue: goToApp, onSignUp: showSignup });
  },
});
```

---

## 5.1. Theming (optional)

All SDK functions (`initializeAuth`, `startSignup`, `startLogin`) accept an optional **`theme`** object. If omitted, the SDK renders its built-in warm-orange theme. If provided, only the specified properties are overridden — everything else keeps the default.

| Property | Type | Default | Description |
|----------|------|---------|-------------|
| `primaryColor` | string (hex) | `#D46B2D` | Buttons, links, active states, progress ring, accent bar |
| `secondaryColor` | string (hex) | — | Reserved for future accent elements |
| `backgroundColor` | string (hex) | `#F5F1EC` | Page / layout background |
| `backgroundImage` | string (URL) | — | Full-bleed background image (an overlay is added automatically) |
| `cardColor` | string (hex) | `#FFFFFF` | Card panel background |
| `textColor` | string (hex) | `#1A1714` | Primary text color |
| `fontFamily` | string | `'Plus Jakarta Sans', system-ui` | CSS font-family |
| `mode` | `'light'` \| `'dark'` \| `'auto'` | `'auto'` | Color mode. `'auto'` detects from `backgroundColor` luminance. |

The SDK **auto-derives** hover colors, glow/shadow colors, gradient endpoints, and input backgrounds from the values you provide. It also runs a WCAG contrast check and logs a warning if `primaryColor` has low contrast against the card.

**Minimal example (just brand colors):**

```javascript
startSignup({
  container: '#auth-container',
  env: 'dev',
  theme: {
    primaryColor: '#2563EB',
  },
});
```

**Full customization:**

```javascript
startSignup({
  container: '#auth-container',
  env: 'dev',
  theme: {
    primaryColor: '#6C63FF',
    secondaryColor: '#2D2B55',
    backgroundColor: '#1A1A2E',
    backgroundImage: 'https://myapp.com/auth-bg.webp',
    cardColor: '#1E1E2E',
    textColor: '#E0E0E0',
    fontFamily: '"DM Sans", sans-serif',
    mode: 'dark',
  },
});
```

**Built-in presets** are available via `THEME_PRESETS`:

```javascript
import { startSignup, THEME_PRESETS } from 'central-auth-sdk';

startSignup({
  container: '#auth',
  env: 'dev',
  theme: THEME_PRESETS.midnight,  // 'default' | 'dark' | 'ocean' | 'forest' | 'purple' | 'rose' | 'midnight'
});
```

You can also spread a preset and override individual properties:

```javascript
theme: { ...THEME_PRESETS.ocean, fontFamily: '"Poppins", sans-serif' }
```

Theme can be set once via `initializeAuth` and overridden per flow:

```javascript
const auth = initializeAuth({
  env: 'dev',
  theme: { primaryColor: '#E11D48' },
});

auth.startSignup({});  // uses rose primary
auth.startLogin({ theme: { primaryColor: '#2563EB' } });  // overrides to blue for login
```

---

## 6. startLogin(config)

Starts the **login flow**. If the parent enables **only one** login method, the SDK skips the method picker and goes straight to that flow.

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `container` | string \| HTMLElement | yes* | Where to render |
| `env` | string | no | Environment: `'local'` \| `'dev'` \| `'staging'` \| `'prod'` (default from init or `'local'`) |
| `appIdentifier` | string | no | Optional. When provided, sent with login/OAuth API requests; omit to not send. |
| **`loginMethods`** | object | no | Which login methods are enabled (see below) |
| `frsAsSecondFactor` | boolean | no | Require face verification after password/OTP/social |
| **`onSignUp()`** | function | no | Called when user clicks **Sign up** on the login screen (e.g. unmount login and start signup in the **same container**). |
| **`onLoginComplete(payload)`** | function | no | Called **once** when login completes. `payload`: `identifier` + any fields from final API (e.g. `access_token`, `refresh_token`). |
| **`onContinue()`** | function | no | Called when user clicks **Continue to application** on the success screen. |

**Login methods** (`loginMethods`):

| Key | Description |
|-----|-------------|
| `emailPassword` | Email + Password |
| `mobilePassword` | Mobile + Password |
| `emailOtp` | Email + OTP |
| `mobileOtp` | Mobile + OTP |
| `social.google` | Google sign-in |
| `social.microsoft` | Microsoft sign-in |
| `emailFrs` | Email + Face only (no password/OTP) |

**Email + FRS:** On the face capture screen, if the user has no webcam, they can click **“No webcam? Sign in with OTP instead”**. The SDK sends an OTP to the email they entered and switches to the OTP step so they can complete login without face capture. No extra configuration is required.

**Example — single method (no method picker):**

```javascript
startLogin({
  container: '#auth-container',
  env: 'dev',
  appIdentifier: 'my-app',
  loginMethods: { emailFrs: true },
  onLoginComplete(payload) {
    saveToken(payload.access_token);
    instance.unmount();
    redirectToApp();
  },
  onContinue() {
    instance.unmount();
    redirectToApp();
  },
  onSignUp() {
    instance.unmount();
    startSignup({ container: '#auth-container', env: 'dev', appIdentifier: '...', onContinue: goToApp, onSwitchToLogin: showLoginFrs });
  },
});
```

**Example — multiple methods (user sees method picker):**

```javascript
startLogin({
  container: '#auth-container',
  env: 'dev',
  appIdentifier: 'my-app',
  loginMethods: {
    emailPassword: true,
    emailOtp: true,
    social: { google: true, microsoft: true },
    emailFrs: true,
  },
  frsAsSecondFactor: true,
  onLoginComplete(payload) { /* ... */ },
  onContinue() { /* ... */ },
  onSignUp() { /* ... */ },
});
```

---

## 6.1. Switching between signup and login in the same container

To keep the user inside the SDK (same container) when they tap **Sign in** or **Sign up**:

- **From signup:** Pass **`onSwitchToLogin()`**. When the user clicks “Already have an account? Sign in”, call it to unmount signup and start login (e.g. `startLogin({ container, loginMethods: { emailFrs: true }, onContinue, onSignUp: showSignup })`).
- **From login:** Pass **`onSignUp()`**. When the user clicks “Don’t have an account? Sign up”, call it to unmount login and start signup (e.g. `startSignup({ container, onContinue, onSwitchToLogin: showLoginFrs })`).

Define `showSignup` and `showLoginFrs` (or your equivalents) so each starts the other flow in the same container and passes the other callback for the reverse link.

---

## 7. Instance API (returned by startSignup / startLogin)

Each call to `startSignup` or `startLogin` returns an instance (or `null` if the container is invalid):

| Method | Description |
|--------|-------------|
| **`instance.unmount()`** | Removes the SDK UI from the DOM. |
| **`instance.getState()`** | Returns current flow state (e.g. `email`, `mobile`, `userId`, `signupResult` / `loginResult`). After completion, `signupResult` or `loginResult` holds the raw final API response. |
| **`instance.getCurrentStep()`** | Current step id (e.g. `'email'`, `'password'`, `'success'`). |
| **`instance.getFlow()`** | Reference to the internal flow controller (for advanced use). |

**Example:**

```javascript
const instance = startLogin({ container: '#auth', loginMethods: { emailPassword: true } });
// Later:
const state = instance.getState();
const step = instance.getCurrentStep();
instance.unmount();
```

---

## 8. Getting tokens and details back

- **Signup:** Pass **`onSignupComplete(payload)`**. The SDK calls it once when signup finishes. `payload` includes `email`, `mobile`, `userId` and whatever your **final signup API** returns (e.g. `access_token`, `refresh_token`). Your backend should return these in the final signup response (e.g. `POST /signup/fr/enroll`).
- **Login:** Pass **`onLoginComplete(payload)`**. The SDK calls it once when login finishes. `payload` includes `identifier` and whatever your **final login API** returns (e.g. `access_token`, `refresh_token`). Your backend should return these in the final login response (e.g. `POST /login/custom`, `POST /otp/verify`, etc.).

You can also read **`instance.getState()`** after the flow completes; it includes **`signupResult`** or **`loginResult`** (the raw final API response).

---

## 9. Returning to the parent application

When the user clicks **Continue to application** on the success screen, the SDK calls **`onContinue()`** if you provided it. Use it to unmount the SDK and show your app (e.g. redirect or switch view):

```javascript
onContinue() {
  instance.unmount();
  window.location.href = '/dashboard';
  // or: showYourAppView();
}
```

---

## 10. Full integration example

```javascript
import { initializeAuth, startSignup, startLogin } from 'central-auth-sdk';
import 'central-auth-sdk/styles.css';

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

let currentInstance = null;

function goToApp() {
  if (currentInstance) currentInstance.unmount();
  currentInstance = null;
  document.getElementById('auth-container').style.display = 'none';
  document.getElementById('app-root').style.display = 'block';
}

function showSignup() {
  if (currentInstance) currentInstance.unmount();
  document.getElementById('auth-container').style.display = 'block';
  currentInstance = auth.startSignup({
    onSignupComplete(payload) {
      saveToken(payload.access_token);
      goToApp();
    },
    onContinue: goToApp,
    onSwitchToLogin: showLoginFrs,
  });
}

function showLoginFrs() {
  if (currentInstance) currentInstance.unmount();
  document.getElementById('auth-container').style.display = 'block';
  currentInstance = auth.startLogin({
    loginMethods: { emailFrs: true },
    onLoginComplete(payload) {
      saveToken(payload.access_token);
      goToApp();
    },
    onContinue: goToApp,
    onSignUp: showSignup,
  });
}

function showLogin(loginMethods = { emailPassword: true }) {
  if (currentInstance) currentInstance.unmount();
  document.getElementById('auth-container').style.display = 'block';
  currentInstance = auth.startLogin({
    loginMethods,
    onLoginComplete(payload) {
      saveToken(payload.access_token);
      goToApp();
    },
    onContinue: goToApp,
    onSignUp: showSignup,
  });
}

function saveToken(token) {
  if (token) localStorage.setItem('access_token', token);
}

showLogin();
```

---

## 11. Backend requirements

- **CORS:** Your API must allow requests from your app’s origin (e.g. `Access-Control-Allow-Origin`).
- **Signup:** The SDK calls your signup endpoints (e.g. `/signup/start`, `/signup/email/verify`, `/signup/fr/enroll`). The **final** response can include `access_token`, `refresh_token`, etc.; the SDK forwards them in `onSignupComplete(payload)` and `getState().signupResult`.
- **Login:** The SDK calls your login endpoints (e.g. `/login/custom`, `/otp/verify`, `/login/email/fr`). The **final** response can include tokens; the SDK forwards them in `onLoginComplete(payload)` and `getState().loginResult`.
- **OAuth:** For Google/Microsoft, configure your backend with the same redirect URI your app uses. The SDK reads `login_token` and `provider` from the URL after redirect and continues the flow.
- **app_identifier:** When the parent app passes **`appIdentifier`**, the SDK sends it as `app_identifier` on login-related requests (e.g. `/login/custom`, `/login/email/fr`, OAuth start URLs, social mobile/FR). If the parent omits it, the SDK does not send the parameter.

For endpoint details and request/response shapes, see **API_INTEGRATION.md** and your backend docs.
