Skip to content

Single Sign-On (SSO) Setup

This guide walks through setting up Single Sign-On (SSO) via SSOReady for Self-Managed Kindo.

SSOReady Components

SSOReady consists of four services:

ServicePortPurpose
ssoready-auth9080Authentication service
ssoready-api9081API service
ssoready-app9082Web application
ssoready-admin9083IT admin self-serve interface

Environment Variables

ssoready-auth

  • AUTH_SERVE_ADDR
  • AUTH_DB — PostgreSQL connection string
  • AUTH_BASE_URL
  • AUTH_DEFAULT_ADMIN_TEST_MODE_URL
  • AUTH_SAML_STATE_SIGNING_KEY — Generate with openssl rand -hex 32

ssoready-api

  • API_SERVE_ADDR
  • API_DB — PostgreSQL connection string
  • API_DEFAULT_AUTH_URL
  • API_DEFAULT_ADMIN_SETUP_URL
  • API_SAML_STATE_SIGNING_KEY — Must match AUTH_SAML_STATE_SIGNING_KEY
  • API_GOOGLE_OAUTH_CLIENT_ID (optional, for Google login)
  • API_MICROSOFT_OAUTH_CLIENT_ID, API_MICROSOFT_OAUTH_CLIENT_SECRET, API_MICROSOFT_OAUTH_REDIRECT_URI (optional, for Microsoft login)

ssoready-app

  • APP_SERVE_PORT, APP_APP_URL, APP_PUBLIC_API_URL, APP_API_URL
  • APP_GOOGLE_OAUTH_CLIENT_ID (optional)
  • APP_MICROSOFT_OAUTH_CLIENT_ID, APP_MICROSOFT_OAUTH_REDIRECT_URI (optional)

ssoready-admin

  • ADMIN_SERVE_PORT, ADMIN_API_URL

Kindo Frontend (Next)

  • SSOREADY_API_URL, SSOREADY_AUTH_URL
  • SSOREADY_API_KEY, SSOREADY_OAUTH_CLIENT_ID, SSOREADY_OAUTH_CLIENT_SECRET (configured after setup)

Initial Setup

Run Migration

Only needed once during initial setup:

Terminal window
docker run --network=host ssoready/ssoready-migrate:sha-<version> \
-d '<postgresql_url>' up

Configure Login Methods

Update the optional authentication variables in ssoready-app and ssoready-api for your desired login methods (Google, Microsoft, etc.).

Setup Steps

  1. Enable the management API for the SSOReady organization:

    -- Find the org
    SELECT id, entitled_management_api FROM app_organizations;
    -- Enable management API
    UPDATE app_organizations
    SET entitled_management_api = TRUE
    WHERE id = 'actual_org_id';
  2. Create environments with:

    • Redirect URL: https://your-kindo-domain/ssoready-callback
    • OAuth Redirect URI: https://your-kindo-domain/api/auth/callback/ssoready-saml
  3. Create organizations within the environment. Add the domain to both External ID and Domains fields.

    Creating an organization in SSOReady with External ID and Domains fields

    SSOReady organization configuration view

  4. Create API keys: In the SSOReady app, navigate to API Keys and create a key with Management API Access enabled. Set the SSOREADY_API_KEY in the Next app.

    SSOReady API Keys page with Management API Access toggle

    SSOReady API key management showing the key creation interface

  5. Create a SAML OAuth Client: Set SSOREADY_OAUTH_CLIENT_ID and SSOREADY_OAUTH_CLIENT_SECRET in the Next app.

    Creating a SAML OAuth Client in SSOReady

Create Organization and User in Kindo

The SSOReady org ID is shown next to the company name in the SSOReady dashboard:

SSOReady dashboard showing the organization ID

Run this SQL to create the first organization and admin user:

DO $$
DECLARE
v_user_entity_id VARCHAR := gen_random_uuid()::VARCHAR;
v_org_entity_id VARCHAR := gen_random_uuid()::VARCHAR;
v_org_dlp_config_id VARCHAR := gen_random_uuid()::VARCHAR;
v_org_settings_id VARCHAR := gen_random_uuid()::VARCHAR;
v_credit_transaction_id VARCHAR := gen_random_uuid()::VARCHAR;
v_sso_domain_id VARCHAR := gen_random_uuid()::VARCHAR;
p_email VARCHAR := '[email protected]'; -- Replace
p_name VARCHAR := 'Admin Name'; -- Replace
p_user_id VARCHAR := '<cuid>'; -- Generate a CUID
p_org_id VARCHAR := '<cuid>'; -- Generate a CUID
p_sso_ready_org_id VARCHAR := NULL; -- SSOReady org ID
p_sso_domain VARCHAR := NULL; -- SSO domain
BEGIN
INSERT INTO "Entity" (id) VALUES (v_org_entity_id);
INSERT INTO "Entity" (id) VALUES (v_user_entity_id);
INSERT INTO "DlpFiltersConfig" (id) VALUES (v_org_dlp_config_id);
INSERT INTO "OrgSettings" (id) VALUES (v_org_settings_id);
INSERT INTO "Org" (
id, "createdAt", "updatedAt", "paymentTier", "entityId",
"baseDlpFiltersConfigId", "settingsId", "ssoReadyOrgId"
) VALUES (
p_org_id, NOW(), NOW(), 'ENTERPRISE', v_org_entity_id,
v_org_dlp_config_id, v_org_settings_id, p_sso_ready_org_id
);
IF p_sso_domain IS NOT NULL THEN
INSERT INTO "OrgSsoDomain" (id, "orgId", domain, "createdAt", "updatedAt")
VALUES (v_sso_domain_id, p_org_id, LOWER(p_sso_domain), NOW(), NOW());
END IF;
INSERT INTO "CreditTransaction" (
id, "createdAt", "orgId", type, amount, "creditsPerUsd"
) VALUES (
v_credit_transaction_id, NOW(), p_org_id,
'INITIAL_ALLOTMENT', 2000000, 10000
);
INSERT INTO "User" (
id, name, email, "orgId", "orgRole",
"createdAt", "updatedAt", "idpId", "entityId"
) VALUES (
p_user_id, p_name, p_email, p_org_id, 'Admin',
NOW(), NOW(), NULL, v_user_entity_id
);
END $$;

Establish SAML Connection

  1. Log in to the SSOReady app (port 9082).

  2. Create a self-serve setup link (without SCIM). Copy the one-time-use URL.

    Creating a self-serve setup link in SSOReady

    The self-serve setup URL ready to copy

  3. Navigate to the link and follow instructions. Set up firstName and lastName in the SAML attributes if names should appear in the Kindo app.

    SAML attribute mapping in Okta showing firstName and lastName fields

  4. Verify the SAML connection appears in the listed connections.

    Verified SAML connection in the SSOReady connections list

  5. SSO sign-in and JIT (Just-In-Time) provisioning are now enabled. Admins can toggle SSO enforcement.

Useful SQL Queries

Update SSOReady org ID:

UPDATE "Org"
SET "ssoReadyOrgId" = '<ssoReadyOrgId>'
WHERE id = '<kindoOrgId>';

Enforce SSO:

UPDATE "OrgSettings"
SET "ssoEnforced" = true
WHERE id = (SELECT "settingsId" FROM "Org" WHERE id = '<kindoOrgId>');

Add SSO domain:

INSERT INTO "OrgSsoDomain" (id, "orgId", domain, "createdAt", "updatedAt")
VALUES (gen_random_uuid(), '<kindoOrgId>', 'yourdomain.com', NOW(), NOW());