Skip to main content

Overview

The sso sub-client provides enterprise-grade single sign-on for your developer organization. It supports multiple identity provider connections (OIDC, SAML 2.0, and LDAP), domain-based enforcement, JIT (just-in-time) provisioning, and session management. Compatible with Okta, Azure AD, Google Workspace, Auth0, OneLogin, PingFederate, OpenLDAP, FreeIPA, and any SAML 2.0, OIDC, or LDAP-compliant provider.
// Create an enterprise SSO connection
const conn = await grantex.sso.createConnection({
  name: 'Okta Production',
  protocol: 'oidc',
  issuerUrl: 'https://mycompany.okta.com',
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  domains: ['mycompany.com'],
  jitProvisioning: true,
});

Enterprise SSO Connections

sso.createConnection()

Create a new SSO identity provider connection. You can create multiple connections for different domains or providers.
const conn = await grantex.sso.createConnection({
  name: 'Okta Production',
  protocol: 'oidc',
  issuerUrl: 'https://mycompany.okta.com',
  clientId: 'your-okta-client-id',
  clientSecret: 'your-okta-client-secret',
  domains: ['mycompany.com', 'mycompany.org'],
  jitProvisioning: true,
  defaultRole: 'member',
});

console.log(conn.id);              // 'sso_conn_01HX...'
console.log(conn.name);            // 'Okta Production'
console.log(conn.protocol);        // 'oidc'
console.log(conn.status);          // 'active'
console.log(conn.domains);         // ['mycompany.com', 'mycompany.org']
console.log(conn.jitProvisioning); // true
console.log(conn.createdAt);       // '2026-03-29T12:00:00Z'

SAML example

const samlConn = await grantex.sso.createConnection({
  name: 'Azure AD SAML',
  protocol: 'saml',
  metadataUrl: 'https://login.microsoftonline.com/.../federationmetadata/2007-06/federationmetadata.xml',
  assertionConsumerServiceUrl: 'https://yourapp.com/sso/saml/callback',
  entityId: 'https://yourapp.com/saml/metadata',
  domains: ['contoso.com'],
  jitProvisioning: true,
  attributeMapping: {
    email: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress',
    name: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/displayname',
  },
});

Parameters

name
string
required
A human-readable name for this connection (e.g. "Okta Production").
protocol
'oidc' | 'saml' | 'ldap'
required
The SSO protocol. Use "oidc" for OpenID Connect, "saml" for SAML 2.0, or "ldap" for LDAP directory authentication.
issuerUrl
string
The OIDC issuer URL. Required when protocol is "oidc".
clientId
string
OAuth 2.0 client ID from your identity provider. Required when protocol is "oidc".
clientSecret
string
OAuth 2.0 client secret from your identity provider. Required when protocol is "oidc".
metadataUrl
string
The SAML metadata URL. Required when protocol is "saml".
assertionConsumerServiceUrl
string
The SAML ACS URL where the IdP posts assertions. Required when protocol is "saml".
entityId
string
The SAML service provider entity ID. Required when protocol is "saml".
domains
string[]
Email domains to associate with this connection. Users with matching email domains are automatically routed to this IdP.
jitProvisioning
boolean
Enable just-in-time user provisioning. When true, users are automatically created on first login. Defaults to false.
defaultRole
string
The default role assigned to JIT-provisioned users (e.g. "member", "admin").
attributeMapping
Record<string, string>
Custom attribute mapping for SAML assertions. Maps Grantex fields to IdP attribute names.

Response: SsoConnection

id
string
Unique connection identifier (e.g. sso_conn_01HX...).
name
string
The connection display name.
protocol
'oidc' | 'saml' | 'ldap'
The SSO protocol.
status
'active' | 'inactive' | 'error'
Current connection status.
domains
string[]
Associated email domains.
jitProvisioning
boolean
Whether JIT provisioning is enabled.
createdAt
string
ISO 8601 creation timestamp.
updatedAt
string
ISO 8601 last-updated timestamp.
The clientSecret is never returned in responses. It is stored securely on the server.

sso.listConnections()

List all SSO connections for your organization.
const connections = await grantex.sso.listConnections();

for (const conn of connections.connections) {
  console.log(`${conn.name} (${conn.protocol}) - ${conn.status}`);
  console.log(`  Domains: ${conn.domains.join(', ')}`);
}

Response: SsoConnectionList

connections
SsoConnection[]
Array of SSO connection objects.

sso.getConnection()

Retrieve a single SSO connection by ID.
const conn = await grantex.sso.getConnection('sso_conn_01HX...');

console.log(conn.name);     // 'Okta Production'
console.log(conn.protocol); // 'oidc'
console.log(conn.status);   // 'active'

Parameters

connectionId
string
required
The connection ID to retrieve.

Response

Returns an SsoConnection object.

sso.updateConnection()

Update an existing SSO connection.
const updated = await grantex.sso.updateConnection('sso_conn_01HX...', {
  name: 'Okta Production (updated)',
  jitProvisioning: false,
  domains: ['mycompany.com', 'mycompany.org', 'subsidiary.com'],
});

console.log(updated.name);    // 'Okta Production (updated)'
console.log(updated.domains); // ['mycompany.com', 'mycompany.org', 'subsidiary.com']

Parameters

connectionId
string
required
The connection ID to update.
name
string
Updated display name.
domains
string[]
Updated list of associated email domains.
jitProvisioning
boolean
Enable or disable JIT provisioning.
defaultRole
string
Updated default role for JIT-provisioned users.
attributeMapping
Record<string, string>
Updated SAML attribute mapping.

Response

Returns the updated SsoConnection object.

sso.deleteConnection()

Delete an SSO connection. Users associated with this connection will no longer be able to log in via SSO.
await grantex.sso.deleteConnection('sso_conn_01HX...');
// Returns void -- connection is removed

Parameters

connectionId
string
required
The connection ID to delete.

Response

Returns void.
Deleting a connection immediately disables SSO login for all users routed through it. Ensure you have an alternative authentication method configured before removing a connection.

sso.testConnection()

Test an SSO connection to verify that the IdP configuration is correct and reachable.
const test = await grantex.sso.testConnection('sso_conn_01HX...');

console.log(test.success);      // true
console.log(test.message);      // 'Connection verified successfully'
console.log(test.responseTime); // 142 (ms)

Parameters

connectionId
string
required
The connection ID to test.

Response: SsoTestResult

success
boolean
Whether the connection test passed.
message
string
Human-readable result message.
responseTime
number
IdP response time in milliseconds.

Enforcement

sso.setEnforcement()

Enforce SSO login for your organization. When enabled, all members must authenticate through an SSO connection.
const enforcement = await grantex.sso.setEnforcement({
  enforced: true,
  exemptRoles: ['owner'],
});

console.log(enforcement.enforced);    // true
console.log(enforcement.exemptRoles); // ['owner']

Parameters

enforced
boolean
required
Whether SSO login is enforced for all organization members.
exemptRoles
string[]
Roles exempt from SSO enforcement (e.g. ["owner"]). Exempt users can still log in with API keys.

Response: SsoEnforcement

enforced
boolean
Whether SSO enforcement is active.
exemptRoles
string[]
Roles that are exempt from the enforcement policy.

Session Management

sso.listSessions()

List active SSO sessions for your organization.
const sessions = await grantex.sso.listSessions();

for (const session of sessions.sessions) {
  console.log(`${session.email} - ${session.connectionName} - expires ${session.expiresAt}`);
}

Response: SsoSessionList

sessions
SsoSession[]
Array of active SSO session objects.
Each SsoSession contains:
id
string
Session identifier.
email
string
The user’s email address.
connectionId
string
The SSO connection used for this session.
connectionName
string
Display name of the SSO connection.
createdAt
string
ISO 8601 session creation timestamp.
expiresAt
string
ISO 8601 session expiration timestamp.

sso.revokeSession()

Revoke an active SSO session, forcing the user to re-authenticate.
await grantex.sso.revokeSession('sso_sess_01HX...');
// Returns void -- session is revoked

Parameters

sessionId
string
required
The session ID to revoke.

Response

Returns void.

Enterprise Login Flow

sso.getLoginUrl() (enterprise)

Get the SSO authorization URL for a user based on their email domain. The domain is matched against configured connections to route the user to the correct IdP.
const login = await grantex.sso.getLoginUrl({
  domain: 'mycompany.com',
  redirectUri: 'https://yourapp.com/sso/callback',
});

console.log(login.authorizeUrl);
// → 'https://mycompany.okta.com/oauth2/v1/authorize?client_id=...&redirect_uri=...'
console.log(login.connectionId);  // 'sso_conn_01HX...'
console.log(login.protocol);     // 'oidc'
// Redirect the user to login.authorizeUrl

Parameters

domain
string
required
The email domain to match against configured SSO connections (e.g. "mycompany.com").
redirectUri
string
Override the redirect URI for this login request.

Response: SsoLoginResponse

authorizeUrl
string
The full authorization URL. Redirect the user here.
connectionId
string
The matched SSO connection ID.
protocol
'oidc' | 'saml' | 'ldap'
The protocol of the matched connection.

sso.handleOidcCallback()

Handle the callback from an OIDC identity provider. Exchanges the authorization code for user information and provisions the user if JIT is enabled.
const result = await grantex.sso.handleOidcCallback({
  code: 'oidc_auth_code',
  state: 'csrf_state',
});

console.log(result.email);        // 'alice@mycompany.com'
console.log(result.name);         // 'Alice Smith'
console.log(result.sub);          // 'okta|abc123'
console.log(result.developerId);  // 'dev_01HXYZ...'
console.log(result.connectionId); // 'sso_conn_01HX...'
console.log(result.provisioned);  // true (if JIT-created)

Parameters

code
string
required
The authorization code from the OIDC callback.
state
string
required
The state parameter from the callback (used for CSRF protection).

Response: SsoCallbackResponse

email
string | null
The user’s email address from the IdP.
name
string | null
The user’s display name from the IdP.
sub
string | null
The user’s subject identifier from the IdP.
developerId
string
The Grantex developer ID that the user has been mapped to.
connectionId
string
The SSO connection that handled this authentication.
provisioned
boolean
Whether the user was just-in-time provisioned during this login.

sso.handleSamlCallback()

Handle the callback from a SAML 2.0 identity provider. Validates the SAML assertion and provisions the user if JIT is enabled.
const result = await grantex.sso.handleSamlCallback({
  samlResponse: req.body.SAMLResponse,
  relayState: req.body.RelayState,
});

console.log(result.email);        // 'bob@contoso.com'
console.log(result.name);         // 'Bob Jones'
console.log(result.developerId);  // 'dev_01HXYZ...'
console.log(result.connectionId); // 'sso_conn_02HX...'
console.log(result.provisioned);  // false

Parameters

samlResponse
string
required
The base64-encoded SAML response from the IdP.
relayState
string
The RelayState parameter from the SAML callback.

Response

Returns the same SsoCallbackResponse as handleOidcCallback().

sso.handleLdapCallback()

Authenticate a user via LDAP bind. Unlike OIDC and SAML which use browser redirects, LDAP authentication submits credentials directly. Grantex binds to the LDAP directory, verifies the user’s password, reads their attributes and group memberships, maps groups to scopes, and provisions the user if JIT is enabled.
const result = await grantex.sso.handleLdapCallback({
  username: 'alice',
  password: 'user-password',
  connectionId: 'sso_conn_03HX...',
});

console.log(result.email);        // 'alice@mycompany.com'
console.log(result.name);         // 'Alice Smith'
console.log(result.developerId);  // 'dev_01HXYZ...'
console.log(result.connectionId); // 'sso_conn_03HX...'
console.log(result.provisioned);  // true (if JIT-created)

Parameters

username
string
required
The user’s LDAP username (e.g. uid, sAMAccountName, or full DN).
password
string
required
The user’s LDAP password for bind authentication.
connectionId
string
required
The SSO connection ID for the LDAP directory.

Response

Returns the same SsoCallbackResponse as handleOidcCallback().
LDAP credentials are never stored by Grantex. They are used only for the bind operation and discarded immediately after authentication.

Full Enterprise SSO Flow Example

import { Grantex } from '@grantex/sdk';
import express from 'express';

const grantex = new Grantex({ apiKey: process.env.GRANTEX_API_KEY });
const app = express();
app.use(express.urlencoded({ extended: true }));

// Step 1: Create SSO connections (one-time setup)
await grantex.sso.createConnection({
  name: 'Okta Production',
  protocol: 'oidc',
  issuerUrl: 'https://mycompany.okta.com',
  clientId: process.env.OKTA_CLIENT_ID,
  clientSecret: process.env.OKTA_CLIENT_SECRET,
  domains: ['mycompany.com'],
  jitProvisioning: true,
  defaultRole: 'member',
});

await grantex.sso.createConnection({
  name: 'Azure AD SAML',
  protocol: 'saml',
  metadataUrl: process.env.AZURE_METADATA_URL,
  assertionConsumerServiceUrl: 'https://yourapp.com/sso/saml/callback',
  entityId: 'https://yourapp.com/saml/metadata',
  domains: ['contoso.com'],
  jitProvisioning: true,
});

// Step 2: Enforce SSO for the organization
await grantex.sso.setEnforcement({
  enforced: true,
  exemptRoles: ['owner'],
});

// Step 3: Redirect user to SSO login based on email domain
app.get('/sso/login', async (req, res) => {
  const { domain } = req.query;
  const login = await grantex.sso.getLoginUrl({
    domain: domain as string,
    redirectUri: 'https://yourapp.com/sso/callback',
  });
  res.redirect(login.authorizeUrl);
});

// Step 4a: Handle OIDC callback
app.get('/sso/callback', async (req, res) => {
  const { code, state } = req.query;
  const result = await grantex.sso.handleOidcCallback({
    code: code as string,
    state: state as string,
  });

  console.log(`Welcome, ${result.name} (${result.email})`);
  if (result.provisioned) {
    console.log('New user provisioned via JIT');
  }
  res.redirect('/dashboard');
});

// Step 4b: Handle SAML callback
app.post('/sso/saml/callback', async (req, res) => {
  const result = await grantex.sso.handleSamlCallback({
    samlResponse: req.body.SAMLResponse,
    relayState: req.body.RelayState,
  });

  console.log(`Welcome, ${result.name} (${result.email})`);
  res.redirect('/dashboard');
});

// Admin: List active sessions
app.get('/admin/sso/sessions', async (req, res) => {
  const sessions = await grantex.sso.listSessions();
  res.json(sessions);
});

Legacy Single-Config Methods

The following methods manage a single OIDC configuration per organization. They are retained for backward compatibility. For new integrations, use the enterprise connection methods above which support multiple IdPs, SAML, and domain-based routing.

sso.createConfig()

Create or update the OIDC SSO configuration for your organization.
const config = await grantex.sso.createConfig({
  issuerUrl: 'https://accounts.google.com',
  clientId: 'your-google-client-id',
  clientSecret: 'your-google-client-secret',
  redirectUri: 'https://yourapp.com/sso/callback',
});

console.log(config.issuerUrl);   // 'https://accounts.google.com'
console.log(config.clientId);    // 'your-google-client-id'
console.log(config.redirectUri); // 'https://yourapp.com/sso/callback'
console.log(config.createdAt);   // '2026-02-28T12:00:00Z'
console.log(config.updatedAt);   // '2026-02-28T12:00:00Z'

Parameters

issuerUrl
string
required
The OIDC issuer URL (e.g. https://accounts.google.com).
clientId
string
required
OAuth 2.0 client ID from your identity provider.
clientSecret
string
required
OAuth 2.0 client secret from your identity provider.
redirectUri
string
required
The callback URL that your IdP redirects to after authentication.

Response: SsoConfig

issuerUrl
string
The OIDC issuer URL.
clientId
string
The OAuth 2.0 client ID.
redirectUri
string
The configured callback URL.
createdAt
string
ISO 8601 creation timestamp.
updatedAt
string
ISO 8601 last-updated timestamp.
The clientSecret is never returned in responses. It is stored securely on the server.

sso.getConfig()

Retrieve the current SSO configuration (without the client secret).
const config = await grantex.sso.getConfig();

console.log(config.issuerUrl);   // 'https://accounts.google.com'
console.log(config.clientId);    // 'your-google-client-id'
console.log(config.redirectUri); // 'https://yourapp.com/sso/callback'

Response

Returns an SsoConfig object.

sso.deleteConfig()

Remove the SSO configuration. After deletion, SSO login is disabled for the organization.
await grantex.sso.deleteConfig();
// Returns void -- SSO is now disabled

Response

Returns void.

sso.getLoginUrl() (legacy)

Get the OIDC authorization URL to redirect the user to for SSO login.
const login = await grantex.sso.getLoginUrl('dev_01HXYZ...');

console.log(login.authorizeUrl);
// → 'https://accounts.google.com/o/oauth2/v2/auth?client_id=...&redirect_uri=...&state=...'
// Redirect the user to this URL

Parameters

org
string
required
The developer ID of the organization initiating the SSO login.

Response: SsoLoginResponse

authorizeUrl
string
The full OIDC authorization URL. Redirect the user here.

sso.handleCallback()

Exchange the OIDC authorization code for user information after the identity provider redirects back.
const result = await grantex.sso.handleCallback(code, state);

console.log(result.email);       // 'alice@example.com'
console.log(result.name);        // 'Alice Smith'
console.log(result.sub);         // 'google-oauth2|12345'
console.log(result.developerId); // 'dev_01HXYZ...'

Parameters

code
string
required
The authorization code from the IdP callback.
state
string
required
The state parameter from the IdP callback (used for CSRF protection).

Response: SsoCallbackResponse

email
string | null
The user’s email address from the IdP.
name
string | null
The user’s display name from the IdP.
sub
string | null
The user’s subject identifier from the IdP.
developerId
string
The Grantex developer ID that the user has been mapped to.

Legacy SSO Flow Example

import { Grantex } from '@grantex/sdk';
import express from 'express';

const grantex = new Grantex({ apiKey: process.env.GRANTEX_API_KEY });
const app = express();

// Step 1: Configure SSO (one-time setup)
await grantex.sso.createConfig({
  issuerUrl: 'https://accounts.google.com',
  clientId: process.env.GOOGLE_CLIENT_ID,
  clientSecret: process.env.GOOGLE_CLIENT_SECRET,
  redirectUri: 'https://yourapp.com/sso/callback',
});

// Step 2: Redirect user to SSO login
app.get('/sso/login', async (req, res) => {
  const { authorizeUrl } = await grantex.sso.getLoginUrl('dev_01HXYZ...');
  res.redirect(authorizeUrl);
});

// Step 3: Handle the callback
app.get('/sso/callback', async (req, res) => {
  const { code, state } = req.query;
  const result = await grantex.sso.handleCallback(code as string, state as string);

  // User is authenticated
  console.log(`Welcome, ${result.name} (${result.email})`);
  // Create a session, redirect to dashboard, etc.
  res.redirect('/dashboard');
});