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.nameSAML 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.nameOIDC discovery is fetched automatically from issuer/.well-known/openid-configuration. The id_token is verified using the IdP's JWKS endpoint.
Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /auth/sso/connections | Create SSO connection |
| GET | /auth/sso/connections/:orgId | List connections for org |
| DELETE | /auth/sso/connections/:id | Remove connection |
| GET | /auth/sso/saml/:connectionId | Initiate SAML login (redirect) |
| POST | /auth/sso/saml/:connectionId/acs | SAML assertion consumer |
| GET | /auth/sso/oidc/:connectionId | Initiate OIDC login (redirect) |
| GET | /auth/sso/oidc/:connectionId/callback | OIDC callback |