How to Set Up Single Sign-On (SSO)

Prev Next

This document will guide you through setting up single sign-on (SSO) via SSOReady for SMK.

SSOReady Initial Set Up

Self Hosting & Environment Variables

  • ssoready-auth (port 9080) - Authentication service
    • AUTH_SERVE_ADDR
    • AUTH_DB
    • AUTH_BASE_URL
    • AUTH_DEFAULT_ADMIN_TEST_MODE_URL
    • AUTH_SAML_STATE_SIGNING_KEY
      • Generate it by running openssl rand -hex 32 .
  • ssoready-api (port 9081) - API service
    • API_SERVE_ADDR
    • API_DB
    • API_DEFAULT_AUTH_URL
    • API_DEFAULT_ADMIN_SETUP_URL
    • API_SAML_STATE_SIGNING_KEY
      • Should be same as AUTH_SAML_STATE_SIGNING_KEY
    • (optional) For google authentication:
      • API_GOOGLE_OAUTH_CLIENT_ID
    • (optional) For Microsoft authentication:
      • API_MICROSOFT_OAUTH_CLIENT_ID
      • API_MICROSOFT_OAUTH_CLIENT_SECRET
      • API_MICROSOFT_OAUTH_REDIRECT_URI: APP_APP_URL+/internal/microsoft-callback
  • ssoready-app (port 9082) - Web application on SSOReady’s side
  • ssoready-admin (port 9083) - IT admin’s interface for self-serve
    • ADMIN_SERVE_PORT
    • ADMIN_API_URL
  • Next (Frontend)
    • SSOREADY_API_URL
    • SSOREADY_AUTH_URL
    • For later
      • SSOREADY_API_KEY
      • SSOREADY_OAUTH_CLIENT_ID
      • SSOREADY_OAUTH_CLIENT_SECRET

Migration

Only need to be run once for initial set up.
docker run --network=host ssoready/ssoready-migrate:sha-[deployed version] -d '[postgresql url]' up

Configure Login Methods

The app needs to be configured with desired login methods before signing in. Update the optional variables for authentication in ssoready-app and ssoready-api.

Setup

  1. After login, enable the management api for the ssoready organization that was created.

      -- First, find the org
      SELECT id, entitled_management_api FROM app_organizations;
    
      -- Then update the specific org
      UPDATE app_organizations
      SET entitled_management_api = TRUE
      WHERE id = 'actual_org_id';
    
  2. Create desired environments.

    1. Redirect URL: http://localhost:3000/ssoready-callback
    2. OAuth Redirect URI: http://localhost:3000/api/auth/callback/ssoready-saml
  3. Within the environment, create organization. Add the domain to both external ID and domains.
    Image

Image

Create API keys and SAML OAuth client

  1. In ssoready app, navigate to API Keys, and create an API key. Turn on the Management API Access and set the SSOREADY_API_KEY variable with the API key in Next app.

Image

Image

  1. Create a SAML OAuth Client. Set the SSOREADY_OAUTH_CLIENT_ID variable and SSOREADY_OAUTH_CLIENT_SECRET variable in Next.

Image

Create org&user in SMK

  • Run SQL query
    • Replace [email protected]
    • Replace User Name
    • Replace cuid for p_user_id using https://generateuuid.online/cuid
    • Replace cuid for p_org_id using https://generateuuid.online/cuid
    • Add p_sso_domain
    • Add p_sso_ready_org_id
      • Example) org Id is shown next to the company’s name

Image

  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]';
      p_name VARCHAR := 'User Name';
      p_user_id VARCHAR := 'cuid';  -- Replace with actual user CUID
      p_org_id VARCHAR := 'cuid';    -- Replace with actual org CUID
      p_sso_ready_org_id VARCHAR := NULL;
      p_sso_domain VARCHAR := NULL;
  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);

      -- Create org settings with default values
      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()
          );
          RAISE NOTICE 'Created SSO domain: % for org: %', p_sso_domain, p_org_id;
      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
      );

      RAISE NOTICE 'Created ENTERPRISE user: %, org: % with SSO Ready org ID: %', p_user_id, p_org_id, p_sso_ready_org_id;
  END $$;
  • Additional useful queries
    1. Update ssoReadyOrgId in Org table

      UPDATE "Org"
        SET "ssoReadyOrgId" = {{ ssoReadyOrgId }}
      WHERE "Org".id = {{ kindoOrgId }};
      
    2. Update ssoEnforced in OrgSettings table

      UPDATE "OrgSettings"
        SET "ssoEnforced" = true
      WHERE id = (
        SELECT "settingsId"
        FROM "Org"
        WHERE id = {{ kindoOrgId }}
      );
      
    3. Insert a row into ssoDomains table

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

Establish SAML connection

  1. Login to the local SSO app (port 9082).
  2. Create self-serve setup link (without SCIM at the moment), copy the self-serve URL. Note that the self-serve URL is one time use only.

Image

Image

  1. Navigate to the link, and follow instructions. If the names need to be shown in our app, set up firstName and lastName field in the SAML attributes. EX: Okta

Image

  1. Confirm that the SAML connection is set up (you can verify with listed SAML connections).

Image

  1. After step 6, SSO sign in AND JIT will be enabled. SSO enforcement can be toggled by admins.
  2. Note that Kindo does NOT support IdP initiated login at the moment - but we support simulated IdP initiated login via the following link: https://your_kindo_domain/login?ssoDomain=somedomain.com