> **Building with AI coding agents?** If you're using an AI coding agent, install the official Scalekit plugin. It gives your agent full awareness of the Scalekit API — reducing hallucinations and enabling faster, more accurate code generation.
>
> - **Claude Code**: `/plugin marketplace add scalekit-inc/claude-code-authstack` then `/plugin install <auth-type>@scalekit-auth-stack`
> - **GitHub Copilot CLI**: `copilot plugin marketplace add scalekit-inc/github-copilot-authstack` then `copilot plugin install <auth-type>@scalekit-auth-stack`
> - **Codex**: run the bash installer, restart, then open Plugin Directory and enable `<auth-type>`
> - **Skills CLI** (Windsurf, Cline, 40+ agents): `npx skills add scalekit-inc/skills --list` then `--skill <skill-name>`
>
> `<auth-type>` / `<skill-name>`: `agentkit`, `full-stack-auth`, `mcp-auth`, `modular-sso`, `modular-scim` — [Full setup guide](https://docs.scalekit.com/dev-kit/build-with-ai/)

---

# Add Modular SSO

Enable enterprise SSO for any customer in minutes with built-in SAML and OIDC integrations
LinkButton, Aside, Steps, TabItem, CardGrid, Icon, Badge
 } from '@astrojs/starlight/components';

  AuthSystemsSection,
} from '@/components/templates';

Enterprise customers often require Single Sign-On (SSO) support for their applications. Rather than building custom integrations for every identity provider—such as Okta, Entra ID, or JumpCloud—and managing the detailed configuration of OIDC and SAML protocols, there are more scalable approaches available.

##  See a walkthrough of the integration

##  Review the authentication sequence

After your customer's identity provider verifies the user, Scalekit forwards the authentication response directly to your application. You receive the verified identity claims and handle all subsequent user management—creating accounts, managing sessions, and controlling access—using your own systems.

> Image: Diagram showing the SSO authentication flow: User initiates login → Scalekit handles protocol translation → Identity Provider authenticates → User gains access to your application

This approach gives you maximum flexibility to integrate SSO into existing authentication architectures while offloading the complexity of SAML and OIDC protocol handling to Scalekit.

Modular SSO is designed for applications that maintain their own user database and session management. This lightweight integration focuses solely on identity verification, giving you complete control over user data and authentication flows.

Choose Modular SSO when you:

- Want to manage user records in your own database
- Prefer to implement custom session management logic
- Need to integrate SSO without changing your existing authentication architecture
- Already have existing user management infrastructure

> note: Using Full stack auth?
>
> [Full stack auth](/authenticate/fsa/quickstart/) includes SSO functionality by default. If you're using Full stack auth, you can skip this guide.

### [Build with a coding agent](/dev-kit/build-with-ai/sso/)

### Claude Code

```bash title="Claude REPL" showLineNumbers=false frame="none"
/plugin marketplace add scalekit-inc/claude-code-authstack
```
```bash title="Claude REPL" showLineNumbers=false frame="none"
/plugin install modular-sso@scalekit-auth-stack
```

   ### Codex

```bash title="Terminal" showLineNumbers=false frame="none"
curl -fsSL https://raw.githubusercontent.com/scalekit-inc/codex-authstack/main/install.sh | bash
```
```bash title="Codex" showLineNumbers=false frame="none"
# Restart Codex
# Plugin Directory -> Scalekit Auth Stack -> install modular-sso
```

   ### GitHub Copilot CLI

```bash title="Terminal" showLineNumbers=false frame="none"
copilot plugin marketplace add scalekit-inc/github-copilot-authstack
```
```bash title="Terminal" showLineNumbers=false frame="none"
copilot plugin install modular-sso@scalekit-auth-stack
```

   ### 40+ agents

```bash title="Terminal" showLineNumbers=false frame="none"
npx skills add scalekit-inc/skills --skill modular-sso
```

  

  [Continue building with AI →](/dev-kit/build-with-ai/sso/)

1. ## Configure "Modular Auth" mode

    Ensure your environment is configured in Modular Auth mode.

    1. Go to Dashboard > Settings > Authentication Mode
    2. Select "Modular Auth" and save

    Now you're ready to start integrating SSO into your app! Next, we'll cover how to use the SDK to authenticate users.

2. ## Set up Scalekit

    Use the following instructions to install the SDK for your technology stack.

    ### Node.js

```bash showLineNumbers=false frame="none"
npm install @scalekit-sdk/node
```

   ### Python

```sh showLineNumbers=false frame="none"
pip install scalekit-sdk-python
```

  ### Go

```sh showLineNumbers=false frame="none"
go get -u github.com/scalekit-inc/scalekit-sdk-go
```

   ### Java

```groovy showLineNumbers=false frame="none"
/* Gradle users - add the following to your dependencies in build file */
implementation "com.scalekit:scalekit-sdk-java:2.0.11"
```

```xml showLineNumbers=false frame="none"
<!-- Maven users - add the following to your `pom.xml` -->
<dependency>
    <groupId>com.scalekit</groupId>
    <artifactId>scalekit-sdk-java</artifactId>
    <version>2.0.11</version>
</dependency>
```

    Configure your environment with API credentials. Navigate to **Dashboard > Developers > Settings > API credentials** and copy these values to your `.env` file:

    ```sh showLineNumbers=false title=".env"
    SCALEKIT_ENVIRONMENT_URL=<your-environment-url> # Example: https://acme.scalekit.dev or https://auth.acme.com (if custom domain is set)
    SCALEKIT_CLIENT_ID=<app-client-id> # Example: skc_1234567890abcdef
    SCALEKIT_CLIENT_SECRET=<app-client-secret> # Example: test_abcdef1234567890
    ```

    ### Register redirect URL for your app
    You need to register redirect URL for your application. Go to **Scalekit dashboard** → **Authentication** → **Redirect URLs** and configure:
    - **Allowed callback URLs**: The endpoint where users are sent after successful authentication to exchange authorization codes and retrieve profile information. [Learn more](/guides/dashboard/redirects/#allowed-callback-urls)
    - **Initiate login URL**: The endpoint in your app that redirects users to Scalekit’s `/authorize` endpoint. Required when user starts sign-in directly from their identity provider (IdP-initiated SSO). [Learn more](/guides/dashboard/redirects/#initiate-login-url)

3. ## Redirect the users to their enterprise identity provider login page

   Create an authorization URL to redirect users to Scalekit's sign-in page. Use the Scalekit SDK to construct this URL with your redirect URI and required scopes.

   
   ### Node.js

```javascript showLineNumbers wrap title="authorization-url.js" collapse={1-8} {"Generates URL to customer's identity provider for SSO login": 28-29}
import { Scalekit } from '@scalekit-sdk/node';

const scalekit = new ScalekitClient(
  '',    // Your Scalekit environment URL
  '',          // Unique identifier for your app
  '',
);

const options = {};

// Specify which SSO connection to use (choose one based on your use case)
// These identifiers are evaluated in order of precedence:

// 1. connectionId (highest precedence) - Use when you know the exact SSO connection
options['connectionId'] = 'conn_15696105471768821';

// 2. organizationId - Routes to organization's SSO (useful for multi-tenant apps)
//    If org has multiple connections, the first active one is selected
options['organizationId'] = 'org_15421144869927830';

// 3. loginHint (lowest precedence) - Extracts domain from email to find connection
//    Domain must be registered to the organization (manually via Dashboard or through admin portal during enterprise onboarding)
options['loginHint'] = 'user@example.com';

// redirect_uri: Your callback endpoint that receives the authorization code
// Must match the URL registered in your Scalekit dashboard
const redirectUrl = 'https://your-app.com/auth/callback';

const authorizationURL = scalekit.getAuthorizationUrl(redirectUrl, options);
// Redirect user to this URL to begin SSO authentication
```

   ### Python

```python showLineNumbers wrap title="authorization_url.py" collapse={1-8} {"Generates URL to customer's identity provider for SSO login": 28-32}
from scalekit import ScalekitClient, AuthorizationUrlOptions

scalekit = ScalekitClient(
  '',    # Your Scalekit environment URL
  '',          # Unique identifier for your app
  ''
)

options = AuthorizationUrlOptions()

# Specify which SSO connection to use (choose one based on your use case)
# These identifiers are evaluated in order of precedence:

# 1. connection_id (highest precedence) - Use when you know the exact SSO connection
options.connection_id = 'conn_15696105471768821'

# 2. organization_id - Routes to organization's SSO (useful for multi-tenant apps)
#    If org has multiple connections, the first active one is selected
options.organization_id = 'org_15421144869927830'

# 3. login_hint (lowest precedence) - Extracts domain from email to find connection
#    Domain must be registered to the organization (manually via Dashboard or through admin portal during enterprise onboarding)
options.login_hint = 'user@example.com'

# redirect_uri: Your callback endpoint that receives the authorization code
# Must match the URL registered in your Scalekit dashboard
redirect_uri = 'https://your-app.com/auth/callback'

authorization_url = scalekit_client.get_authorization_url(
  redirect_uri=redirect_uri,
  options=options
)
# Redirect user to this URL to begin SSO authentication
```

   ### Go

```go showLineNumbers title="authorization_url.go" collapse={1-11} {"Generates URL to customer's identity provider for SSO login": 31-36}
import (
  "github.com/scalekit-inc/scalekit-sdk-go"
)

func main() {
  scalekitClient := scalekit.NewScalekitClient(
    "",  // Your Scalekit environment URL
    "",        // Unique identifier for your app
    ""
  )

  options := scalekitClient.AuthorizationUrlOptions{}

  // Specify which SSO connection to use (choose one based on your use case)
  // These identifiers are evaluated in order of precedence:

  // 1. ConnectionId (highest precedence) - Use when you know the exact SSO connection
  options.ConnectionId = "conn_15696105471768821"

  // 2. OrganizationId - Routes to organization's SSO (useful for multi-tenant apps)
  //    If org has multiple connections, the first active one is selected
  options.OrganizationId = "org_15421144869927830"

  // 3. LoginHint (lowest precedence) - Extracts domain from email to find connection
  //    Domain must be registered to the organization (manually via Dashboard or through admin portal during enterprise onboarding)
  options.LoginHint = "user@example.com"

  // redirectUrl: Your callback endpoint that receives the authorization code
  // Must match the URL registered in your Scalekit dashboard
  redirectUrl := "https://your-app.com/auth/callback"

  authorizationURL := scalekitClient.GetAuthorizationUrl(
    redirectUrl,
    options,
  )
  // Redirect user to this URL to begin SSO authentication
}
```

   ### Java

```java showLineNumbers title="AuthorizationUrl.java"
package com.scalekit;

import com.scalekit.ScalekitClient;
import com.scalekit.internal.http.AuthorizationUrlOptions;

public class Main {

  public static void main(String[] args) {
    ScalekitClient scalekitClient = new ScalekitClient(
      "",  // Your Scalekit environment URL
      "",        // Unique identifier for your app
      ""
    );

    AuthorizationUrlOptions options = new AuthorizationUrlOptions();

    // Specify which SSO connection to use (choose one based on your use case)
    // These identifiers are evaluated in order of precedence:

    // 1. connectionId (highest precedence) - Use when you know the exact SSO connection
    options.setConnectionId("con_13388706786312310");

   // 2. organizationId - Routes to organization's SSO (useful for multi-tenant apps)
   //    If org has multiple connections, the first active one is selected
   options.setOrganizationId("org_13388706786312310");

   // 3. loginHint (lowest precedence) - Extracts domain from email to find connection
   //    Domain must be registered to the organization (manually via Dashboard or through admin portal during enterprise onboarding)
   options.setLoginHint("user@example.com");

    // redirectUrl: Your callback endpoint that receives the authorization code
    // Must match the URL registered in your Scalekit dashboard
    String redirectUrl = "https://your-app.com/auth/callback";

    try {
      String url = scalekitClient
        .authentication()
        .getAuthorizationUrl(redirectUrl, options)
        .toString();
      // Redirect user to this URL to begin SSO authentication
    } catch (Exception e) {
      System.out.println(e.getMessage());
    }
  }
}
```

   ### Direct URL (No SDK)

```sh title="OAuth2 authorization URL" showLineNumbers=false
/oauth/authorize?
  response_type=code&                        # OAuth2 authorization code flow
  client_id=&            # Your Scalekit client ID
  redirect_uri=&               # URL-encoded callback URL
  scope=openid profile email&                # Note: "offline_access" scope is not supported in Modular SSO
  organization_id=org_15421144869927830&     # (Optional) Route by organization
  connection_id=conn_15696105471768821&      # (Optional) Specific SSO connection
  login_hint=user@example.com                # (Optional) Extract domain from email
```

**SSO identifiers** (choose one or more, evaluated in order of precedence):
- `connection_id` - Direct to specific SSO connection (highest precedence)
- `organization_id` - Route to organization's SSO
- `domain_hint` - Lookup connection by domain
- `login_hint` - Extract domain from email (lowest precedence). Domain must be registered to the organization (manually via Dashboard or through admin portal when [onboarding an enterprise customer](/sso/guides/onboard-enterprise-customers/))

```http showLineNumbers=false title="Example with actual values"
https://tinotat-dev.scalekit.dev/oauth/authorize?
  response_type=code&
  client_id=skc_88036702639096097&
  redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fauth%2Fcallback&
  scope=openid%20profile%20email&
  organization_id=org_15421144869927830
```

   

   Enterprise users see their identity provider's login page. Users verify their identity through the authentication policies set by their organization's administrator. Post successful verification, the user profile is [normalized](/sso/guides/user-profile-details/) and sent to your app.

   For details on how Scalekit determines which SSO connection to use, refer to the [SSO identifier precedence rules](/sso/guides/authorization-url/#parameter-precedence).

4. ## Handle IdP-initiated SSO 

   When users start the login process from their identity provider's portal (rather than your application), this is called IdP-initiated SSO. Scalekit converts these requests to secure SP-initiated flows automatically.

   Your initiate login endpoint receives an `idp_initiated_login` JWT parameter containing the user's organization and connection details. Decode this token and generate a new authorization URL to complete the authentication flow securely.

   ```sh showLineNumbers=false wrap
   https://yourapp.com/login?idp_initiated_login=<encoded_jwt_token>
   ```

   Configure your initiate login endpoint in [Dashboard > Authentication > Redirects](/guides/dashboard/redirects/#initiate-login-url)

   
   ### Node.js

```javascript wrap title="handle-idp-initiated.js" collapse={3-7}
// Your initiate login endpoint receives the IdP-initiated login token
const { idp_initiated_login, error, error_description } = req.query;

if (error) {
  return res.status(400).json({ message: error_description });
}

// When users start login from their IdP portal, convert to SP-initiated flow
if (idp_initiated_login) {
  // Decode the JWT to extract organization and connection information
  const claims = await scalekit.getIdpInitiatedLoginClaims(idp_initiated_login);

  const options = {
    connectionId: claims.connection_id,      // Specific SSO connection
    organizationId: claims.organization_id,  // User's organization
    loginHint: claims.login_hint,            // User's email for context
    state: claims.relay_state                // Preserve state from IdP
  };

  // Generate authorization URL and redirect to complete authentication
  const authorizationURL = scalekit.getAuthorizationUrl(
    'https://your-app.com/auth/callback',
    options
  );

  return res.redirect(authorizationURL);
}
```

   ### Python

```python title="handle_idp_initiated.py"  collapse={5-8}
# Your initiate login endpoint receives the IdP-initiated login token
idp_initiated_login = request.args.get('idp_initiated_login')
error = request.args.get('error')
error_description = request.args.get('error_description')

if error:
    raise Exception(error_description)

# When users start login from their IdP portal, convert to SP-initiated flow
if idp_initiated_login:
    # Decode the JWT to extract organization and connection information
    claims = await scalekit.get_idp_initiated_login_claims(idp_initiated_login)

    options = AuthorizationUrlOptions()
    options.connection_id = claims.get('connection_id')      # Specific SSO connection
    options.organization_id = claims.get('organization_id')  # User's organization
    options.login_hint = claims.get('login_hint')            # User's email for context
    options.state = claims.get('relay_state')                # Preserve state from IdP

    # Generate authorization URL and redirect to complete authentication
    authorization_url = scalekit.get_authorization_url(
        redirect_uri='https://your-app.com/auth/callback',
        options=options
    )

    return redirect(authorization_url)
```

   ### Go

```go title="handle_idp_initiated.go" collapse={5-9,30-37}
// Your initiate login endpoint receives the IdP-initiated login token
idpInitiatedLogin := r.URL.Query().Get("idp_initiated_login")
errorDesc := r.URL.Query().Get("error_description")

if errorDesc != "" {
    http.Error(w, errorDesc, http.StatusBadRequest)
    return
}

// When users start login from their IdP portal, convert to SP-initiated flow
if idpInitiatedLogin != "" {
    // Decode the JWT to extract organization and connection information
    claims, err := scalekitClient.GetIdpInitiatedLoginClaims(r.Context(), idpInitiatedLogin)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    options := scalekit.AuthorizationUrlOptions{
        ConnectionId:   claims.ConnectionID,    // Specific SSO connection
        OrganizationId: claims.OrganizationID,  // User's organization
        LoginHint:      claims.LoginHint,       // User's email for context
    }

    // Generate authorization URL and redirect to complete authentication
    authUrl, err := scalekitClient.GetAuthorizationUrl(
        "https://your-app.com/auth/callback",
        options
    )

    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    http.Redirect(w, r, authUrl.String(), http.StatusFound)
}
```

   ### Java

```java title="HandleIdpInitiated.java"
// Your initiate login endpoint receives the IdP-initiated login token
@GetMapping("/login")
public RedirectView handleInitiateLogin(
    @RequestParam(required = false, name = "idp_initiated_login") String idpInitiatedLoginToken,
    @RequestParam(required = false) String error,
    @RequestParam(required = false, name = "error_description") String errorDescription,
    HttpServletResponse response) throws IOException {

    if (error != null) {
        response.sendError(HttpStatus.BAD_REQUEST.value(), errorDescription);
        return null;
    }

    // When users start login from their IdP portal, convert to SP-initiated flow
    if (idpInitiatedLoginToken != null) {
        // Decode the JWT to extract organization and connection information
        IdpInitiatedLoginClaims claims = scalekit
            .authentication()
            .getIdpInitiatedLoginClaims(idpInitiatedLoginToken);

        if (claims == null) {
            response.sendError(HttpStatus.BAD_REQUEST.value(), "Invalid token");
            return null;
        }

        AuthorizationUrlOptions options = new AuthorizationUrlOptions();
        options.setConnectionId(claims.getConnectionID());      // Specific SSO connection
        options.setOrganizationId(claims.getOrganizationID());  // User's organization
        options.setLoginHint(claims.getLoginHint());            // User's email for context

        // Generate authorization URL and redirect to complete authentication
        String authUrl = scalekit
            .authentication()
            .getAuthorizationUrl("https://your-app.com/auth/callback", options)
            .toString();

        response.sendRedirect(authUrl);
        return null;
    }

    return null;
}
```

   

   This approach provides enhanced security by converting IdP-initiated requests to standard SP-initiated flows, protecting against SAML assertion theft and replay attacks.

   Learn more: [IdP-initiated SSO implementation guide](/sso/guides/idp-init-sso/)

5. ## Get user details from the callback

    After successful authentication, Scalekit redirects to your callback URL with an authorization code. Your application exchanges this code for the user's profile information and session tokens.

   1. Add a callback endpoint in your application (typically `https://your-app.com/auth/callback`)
   2. [Register](/guides/dashboard/redirects/#allowed-callback-urls) it in your Scalekit dashboard > Authentication > Redirect URLS > Allowed Callback URLs

   In authentication flow, Scalekit redirects to your callback URL with an authorization code. Your application exchanges this code for the user's profile information.

    
    ### Node.js

```javascript showLineNumbers wrap title="Fetch user profile" {17}
// Extract authentication parameters from the callback request
const {
  code,
  error,
  error_description,
  idp_initiated_login,
  connection_id,
  relay_state
} = req.query;

if (error) {
  // Handle authentication errors returned from the identity provider
}

// Recommended: Process IdP-initiated login flows (when users start from their SSO portal)

const result = await scalekit.authenticateWithCode(code, redirectUri);
const userEmail = result.user.email;

// Create a session for the authenticated user and grant appropriate access permissions
```

    ### Python

```py showLineNumbers title="Fetch user profile"
# Extract authentication parameters from the callback request
code = request.args.get('code')
error = request.args.get('error')
error_description = request.args.get('error_description')
idp_initiated_login = request.args.get('idp_initiated_login')
connection_id = request.args.get('connection_id')
relay_state = request.args.get('relay_state')

if error:
    raise Exception(error_description)

# Recommended: Process IdP-initiated login flows (when users start from their SSO portal)

result = scalekit.authenticate_with_code(code, '<redirect_uri>')

# Access normalized user profile information
user_email = result.user.email

# Create a session for the authenticated user and grant appropriate access permissions
```

    ### Go

```go title="Fetch user profile"
// Extract authentication parameters from the callback request
code := r.URL.Query().Get("code")
error := r.URL.Query().Get("error")
errorDescription := r.URL.Query().Get("error_description")
idpInitiatedLogin := r.URL.Query().Get("idp_initiated_login")
connectionID := r.URL.Query().Get("connection_id")
relayState := r.URL.Query().Get("relay_state")

if error != "" {
  // Handle authentication errors returned from the identity provider
}

// Recommended: Process IdP-initiated login flows (when users start from their SSO portal)

result, err := scalekitClient.AuthenticateWithCode(r.Context(), code, redirectUrl)

if err != nil {
  // Handle token exchange or validation errors
}

// Access normalized user profile information
userEmail := result.User.Email

// Create a session for the authenticated user and grant appropriate access permissions
```

    ### Java

```java showLineNumbers title="Fetch user profile"
// Extract authentication parameters from the callback request
String code = request.getParameter("code");
String error = request.getParameter("error");
String errorDescription = request.getParameter("error_description");
String idpInitiatedLogin = request.getParameter("idp_initiated_login");
String connectionID = request.getParameter("connection_id");
String relayState = request.getParameter("relay_state");

if (error != null && !error.isEmpty()) {
    // Handle authentication errors returned from the identity provider
    return;
}

// Recommended: Process IdP-initiated login flows (when users start from their SSO portal)

try {
    AuthenticationResponse result = scalekit.authentication().authenticateWithCode(code, redirectUrl);
    String userEmail = result.getIdTokenClaims().getEmail();

    // Create a session for the authenticated user and grant appropriate access permissions
} catch (Exception e) {
    // Handle token exchange or validation errors
}
```

    

    The `result` object

   
   ### Node.js

```js title="Validate tokens"
// Validate and decode the ID token from the authentication result
const idTokenClaims = await scalekit.validateToken(result.idToken);

// Validate and decode the access token
const accessTokenClaims = await scalekit.validateToken(result.accessToken);
```

   ### Python

```py title="Validate tokens"
 # Validate and decode the ID token from the authentication result
 id_token_claims = scalekit_client.validate_token(result["id_token"])

 # Validate and decode the access token
 access_token_claims = scalekit_client.validate_token(result["access_token"])
```

   ### Go

```go title="Validate tokens"

 // Validate and decode the access token (uses JWKS from the client)
 accessTokenClaims, err := scalekitClient.GetAccessTokenClaims(ctx, result.AccessToken)
 if err != nil {
     // handle error
 }

```

   ### Java

```java title="Validate tokens"
 // Validate and decode the ID token
 Map idTokenClaims = scalekitClient.validateToken(result.getIdToken());

 // Validate and decode the access token
 Map accessTokenClaims = scalekitClient.validateToken(result.getAccessToken());
```

   

    
        ### Auth result

```js
{
  user: {
    email: 'john@example.com',
    familyName: 'Doe',
    givenName: 'John',
    username: 'john@example.com',
    id: 'conn_70087756662964366;dcc62570-6a5a-4819-b11b-d33d110c7716'
  },
  idToken: 'eyJhbGciOiJSU..bcLQ',
  accessToken: 'eyJhbGciO..',
  expiresIn: 899
}
```

        ### ID token (decoded)

```js
{
  amr: [ 'conn_70087756662964366' ], // SSO connection ID
  at_hash: 'yMGIBg7BkmIGgD6_dZPEGQ',
  aud: [ 'skc_70087756327420046' ],
  azp: 'skc_70087756327420046',
  c_hash: '4x7qsXnlRw6dRC6twnuENw',
  client_id: 'skc_70087756327420046',
  email: 'john@example.com',
  exp: 1758952038,
  family_name: 'Doe',
  given_name: 'John',
  iat: 1758692838,
  iss: '',
  oid: 'org_70087756646187150',
  preferred_username: 'john@example.com',
  sid: 'ses_91646612652163629',
  sub: 'conn_70087756662964366;e964d135-35c7-4a13-a3b4-2579a1cdf4e6'
}
```

        ### Access token (decoded)

```js
 {
  "iss": "",
  "sub": "conn_70087756662964366;dcc62570-6a5a-4819-b11b-d33d110c7716",
  "aud": [
    "skc_70087756327420046"
  ],
  "exp": 1758693916,
  "iat": 1758693016,
  "nbf": 1758693016,
  "client_id": "skc_70087756327420046",
  "jti": "tkn_91646913048216109"
}
```

      

6. ## Test your SSO integration

   Validate your implementation using the **IdP Simulator** and **Test Organization** included in your development environment. Test all three scenarios before deploying to production.

   Your environment includes a pre-configured test organization (found in **Dashboard > Organizations**) with domains like `@example.com` and `@example.org` for testing.

    Pass one of the following connection selectors in your authorization URL:

    - Email address with `@example.com` or `@example.org` domain
    - Test organization's connection ID
    - Organization ID

    This opens the SSO login page (IdP Simulator) that simulates your customer's identity provider login experience.

    > Image: IdP Simulator

   For detailed testing instructions and scenarios, see our [Complete SSO testing guide](/sso/guides/test-sso/)

7. ## Set up SSO with your existing authentication system

    Many applications already use an authentication provider such as Auth0, Firebase, or AWS Cognito. To enable single sign-on (SSO) using Scalekit, configure Scalekit to work with your current authentication provider.

    ### [Auth0](/guides/integrations/auth-systems/auth0)

Integrate Scalekit with Auth0 for enterprise SSO
  ### [Firebase Auth](/guides/integrations/auth-systems/firebase)

Add enterprise authentication to Firebase projects
  ### [AWS Cognito](/guides/integrations/auth-systems/aws-cognito)

Configure Scalekit with AWS Cognito user pools

7. ## Onboard enterprise customers

   Enable SSO for your enterprise customers by creating an organization in Scalekit and providing them access to the Admin Portal. Your customers configure their identity provider settings themselves through a self-service portal.

   **Create an organization** for your customer in [Dashboard > Organizations](https://app.scalekit.com/organizations), then provide Admin Portal access using one of these methods:

   
   ### Shareable link

Generate a secure link your customer can use to access the Admin Portal:

```javascript showLineNumbers=false title="generate-portal-link.js"
// Generate a one-time Admin Portal link for your customer
const portalLink = await scalekit.organization.generatePortalLink(
  'org_32656XXXXXX0438'  // Your customer's organization ID
);

// Share this link with your customer's IT admin via email or messaging
// Example: '/magicLink/8930509d-68cf-4e2c-8c6d-94d2b5e2db43
console.log('Admin Portal URL:', portalLink.location);
```

Send this link to your customer's IT administrator through email, Slack, or your preferred communication channel. They can configure their SSO connection without any developer involvement.

   ### Embedded portal

Embed the Admin Portal directly in your application using an iframe:

```javascript showLineNumbers=false title="embed-portal.js"
// Generate a secure portal link at runtime
const portalLink = await scalekit.organization.generatePortalLink(orgId);

// Return the link to your frontend to embed in an iframe
res.json({ portalUrl: portalLink.location });
```

```html showLineNumbers=false title="admin-settings.html"
<!-- Embed in your application's settings page -->
<iframe
  src="https://random-subdomain.scalekit.dev/magicLink/8930509d-68cf-4e2c-8c6d-94d2b5e2db43"
  width="100%"
  height="600"
  frameborder="0"
  allow="clipboard-write">
</iframe>
```

Customers configure SSO without leaving your application, maintaining a consistent user experience. Listen for UI events from the embedded portal to respond to configuration changes, such as when SSO is enabled or the session expires. See the [Admin portal UI events reference](/reference/admin-portal/ui-events/) for details on handling these events.

Learn more: [Embedded Admin Portal guide](/guides/admin-portal/#embed-the-admin-portal)

   

   **Enable domain verification** for seamless user experience. Once your customer verifies their domain (e.g., `@megacorp.org`), users can sign in without selecting their organization. Scalekit automatically routes them to the correct identity provider based on their email domain.

   **Pre-check SSO availability** before redirecting users. This prevents failed redirects when a user's domain doesn't have SSO configured:

   
   ### Node.js

```javascript showLineNumbers=true title="check-sso-availability.js"
// Extract domain from user's email address
const domain = email.split('@')[1].toLowerCase();  // e.g., "megacorp.org"

// Check if domain has an active SSO connection
const connections = await scalekit.connections.listConnectionsByDomain({
   domain
 });

if (connections.length > 0) {
  // Domain has SSO configured - redirect to identity provider
  const authUrl = scalekit.getAuthorizationUrl(redirectUri, {
    domainHint: domain  // Automatically routes to correct IdP
  });
  return res.redirect(authUrl);
} else {
  // No SSO for this domain - show alternative login methods
  return showPasswordlessLogin();
}
```

   ### Python

```python showLineNumbers=true title="check_sso_availability.py"
# Extract domain from user's email address
domain = email.split('@')[1].lower()  # e.g., "megacorp.org"

# Check if domain has an active SSO connection
connections = scalekit_client.connections.list_connections_by_domain(
    domain=domain
)

if len(connections) > 0:
    # Domain has SSO configured - redirect to identity provider
    options = AuthorizationUrlOptions()
    options.domain_hint = domain  # Automatically routes to correct IdP

    auth_url = scalekit_client.get_authorization_url(
        redirect_uri=redirect_uri,
        options=options
    )
    return redirect(auth_url)
else:
    # No SSO for this domain - show alternative login methods
    return show_passwordless_login()
```

   ### Go

```go showLineNumbers=true title="check_sso_availability.go"
// Extract domain from user's email address
parts := strings.Split(email, "@")
domain := strings.ToLower(parts[1])  // e.g., "megacorp.org"

// Check if domain has an active SSO connection
connections, err := scalekitClient.Connections.ListConnectionsByDomain(domain)
if err != nil {
    // Handle error
    return err
}

if len(connections) > 0 {
    // Domain has SSO configured - redirect to identity provider
    options := scalekit.AuthorizationUrlOptions{
        DomainHint: domain,  // Automatically routes to correct IdP
    }

    authUrl, err := scalekitClient.GetAuthorizationUrl(redirectUri, options)
    if err != nil {
        return err
    }

    c.Redirect(http.StatusFound, authUrl.String())
} else {
    // No SSO for this domain - show alternative login methods
    return showPasswordlessLogin()
}
```

   ### Java

```java showLineNumbers=true title="CheckSsoAvailability.java"
// Extract domain from user's email address
String[] parts = email.split("@");
String domain = parts[1].toLowerCase();  // e.g., "megacorp.org"

// Check if domain has an active SSO connection
List connections = scalekitClient
    .connections()
    .listConnectionsByDomain(domain);

if (connections.size() > 0) {
    // Domain has SSO configured - redirect to identity provider
    AuthorizationUrlOptions options = new AuthorizationUrlOptions();
    options.setDomainHint(domain);  // Automatically routes to correct IdP

    String authUrl = scalekitClient
        .authentication()
        .getAuthorizationUrl(redirectUri, options)
        .toString();

    return new RedirectView(authUrl);
} else {
    // No SSO for this domain - show alternative login methods
    return showPasswordlessLogin();
}
```

   

   This check ensures users only see SSO options when available, improving the login experience and reducing confusion.


---

## More Scalekit documentation

| Resource | What it contains | When to use it |
|----------|-----------------|----------------|
| [/llms.txt](/llms.txt) | Structured index with routing hints per product area | Start here — find which documentation set covers your topic before loading full content |
| [/llms-full.txt](/llms-full.txt) | Complete documentation for all Scalekit products in one file | Use when you need exhaustive context across multiple products or when the topic spans several areas |
| [sitemap-0.xml](https://docs.scalekit.com/sitemap-0.xml) | Full URL list of every documentation page | Use to discover specific page URLs you can fetch for targeted, page-level answers |
