kavachOS
Authentication

SSO

Enterprise single sign-on via SAML 2.0 and OIDC, with JIT user provisioning.

Setup

Configure your identity providers when creating the KavachOS instance:

import { createKavach } from 'kavachos';

const kavach = await createKavach({
  database: { provider: 'sqlite', url: 'kavach.db' },
  sso: { 
    saml: [ 
      {
        id: 'okta', 
        name: 'Okta', 
        entryPoint: 'https://your-org.okta.com/app/appId/sso/saml', 
        issuer: 'https://your-app.com', 
        cert: process.env.OKTA_SAML_CERT, 
        callbackUrl: 'https://your-app.com/api/kavach/auth/sso/saml/conn_id/acs', 
      },
    ],
  }, 
});
import { createKavach } from 'kavachos';

const kavach = await createKavach({
  database: { provider: 'sqlite', url: 'kavach.db' },
  sso: { 
    oidc: [ 
      {
        id: 'azure', 
        name: 'Azure AD', 
        issuer: 'https://login.microsoftonline.com/your-tenant-id/v2.0', 
        clientId: process.env.AZURE_CLIENT_ID, 
        clientSecret: process.env.AZURE_CLIENT_SECRET, 
        callbackUrl: 'https://your-app.com/api/kavach/auth/sso/oidc/conn_id/callback', 
        scopes: ['openid', 'profile', 'email'], 
      },
    ],
  }, 
});

SSO connections

Connections link an org to an identity provider and route by email domain.

// Create a connection for an org
const connection = await kavach.sso.createConnection({ 
  orgId: 'org_acme',
  providerId: 'okta',    // matches the id in your sso config
  type: 'saml',          // 'saml' | 'oidc'
  domain: 'acme.com',    // emails at this domain are routed here
});

// Look up a connection by domain (e.g., to redirect on login)
const conn = await kavach.sso.getConnectionByDomain('alice@acme.com'.split('@')[1]);

// List all connections for an org
const conns = await kavach.sso.listConnections('org_acme');

// Remove a connection
await kavach.sso.removeConnection(connection.id);

JIT provisioning

When a user authenticates through SSO for the first time, KavachOS provisions their account automatically using the identity attributes from the IdP (email and display name from SAML NameID / OIDC email claim). No pre-registration is needed.

User IDs are derived deterministically from the provider and subject, so the same IdP user always maps to the same KavachOS identity.

SAML flow

// 1. Redirect the user to the IdP
const authUrl = await kavach.sso.getSamlAuthUrl(connection.id, '/dashboard');
// redirect to authUrl

// 2. Handle the ACS callback (POST from IdP)
const { user, orgId } = await kavach.sso.handleSamlResponse(
  connection.id,
  samlResponseFromFormData,
);
// user.id, user.email, user.name

SAML responses are verified against the IdP certificate. Unsigned responses are rejected.

OIDC flow

// 1. Redirect the user to the IdP
const authUrl = await kavach.sso.getOidcAuthUrl(connection.id, stateParam);
// redirect to authUrl

// 2. Handle the callback
const { user, orgId } = await kavach.sso.handleOidcCallback(connection.id, codeFromQuery);
// user.id, user.email, user.name

OIDC discovery is fetched automatically from issuer/.well-known/openid-configuration. The id_token is verified using the IdP's JWKS endpoint.

Endpoints

MethodPathDescription
POST/auth/sso/connectionsCreate SSO connection
GET/auth/sso/connections/:orgIdList connections for org
DELETE/auth/sso/connections/:idRemove connection
GET/auth/sso/saml/:connectionIdInitiate SAML login (redirect)
POST/auth/sso/saml/:connectionId/acsSAML assertion consumer
GET/auth/sso/oidc/:connectionIdInitiate OIDC login (redirect)
GET/auth/sso/oidc/:connectionId/callbackOIDC callback

On this page