# How to Use Logto for SSO: Enterprise Single Sign-On Implementation Guide

> Implement enterprise SSO with Logto using OpenID Connect and SAML. Streamline user authentication with automatic sign-on via external identity providers and just-in-time provisioning.

- Repository: [Logto/logto](https://github.com/logto-io/logto)
- Tags: how-to-guide
- Published: 2026-07-03

---

**Logto implements native SSO support through OpenID Connect and SAML connectors that automatically authenticate users via external identity providers, storing federated identities in the `user_sso_identities` table while enabling just-in-time provisioning for enterprise domains.**

Logto is an open-source identity infrastructure that treats single sign-on (SSO) as a first-class feature. The `logto-io/logto` repository provides a complete implementation allowing any OIDC or SAML identity provider to integrate seamlessly into the authentication flow. This guide explains how to configure and implement SSO using Logto's management APIs, interaction endpoints, and frontend hooks.

## Understanding Logto SSO Architecture

Logto's SSO implementation consists of three architectural layers that work together to orchestrate authentication between your application and external identity providers.

### Connector Management Layer

The connector management layer stores SSO configurations in the `sso_connectors` table, including metadata, client credentials, and token storage flags. After successful authentication, identity data returned by the IdP is persisted in the `user_sso_identities` table. This schema design is documented in [`packages/schemas/CHANGELOG.md`](https://github.com/logto-io/logto/blob/main/packages/schemas/CHANGELOG.md) (lines 1319-1322), which introduces these tables for enterprise connector storage.

### Interaction API Layer

The core routing layer in [`packages/core/src/routes/interaction/single-sign-on.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/interaction/single-sign-on.ts) exposes three critical endpoints that drive the SSO flow:

- **`POST /api/interaction/single-sign-on/:connectorId/authorization-url`** – Builds the IdP authorization URL for redirecting users
- **`POST /api/interaction/single-sign-on/:connectorId/authentication`** – Processes the IdP callback, validates token sets, and stores SSO identities
- **`GET /api/interaction/single-sign-on/connectors`** – Returns enabled connectors for a given email domain, enabling just-in-time provisioning decisions

### Verification Helpers Layer

The low-level SSO logic resides in [`packages/core/src/libraries/verification-helpers/single-sign-on.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/libraries/verification-helpers/single-sign-on.ts). This library handles building authorization URLs, exchanging authorization codes for tokens, and persisting federated token sets when the storage flag is enabled. Session-specific SSO data is managed through [`single-sign-on-session.ts`](https://github.com/logto-io/logto/blob/main/single-sign-on-session.ts), which maintains the `sso_identities` claim containing `details`, `issuer`, and `identityId` fields.

## Configuring SSO Connectors via Management API

To enable SSO, first create a connector configuration using Logto's Management API. The endpoint `POST /api/sso-connectors` accepts OIDC or SAML configurations and associates them with specific email domains.

```http
POST https://<your-logto-domain>/api/sso-connectors
Content-Type: application/json
Authorization: Bearer <management-api-token>

{
  "name": "Okta OIDC",
  "type": "oidc",
  "connectorId": "okta-oidc",
  "config": {
    "clientId": "YOUR_CLIENT_ID",
    "clientSecret": "YOUR_CLIENT_SECRET",
    "authorizationEndpoint": "https://dev-123.okta.com/oauth2/v1/authorize",
    "tokenEndpoint": "https://dev-123.okta.com/oauth2/v1/token",
    "userinfoEndpoint": "https://dev-123.okta.com/oauth2/v1/userinfo",
    "issuer": "https://dev-123.okta.com"
  },
  "domains": ["example.com"],
  "metadata": {
    "tokenStorageEnabled": true
  }
}

```

The `domains` array determines which email addresses trigger this specific connector. Setting `tokenStorageEnabled` to `true` allows Logto to store the federated token set, enabling later retrieval of IdP access tokens without re-authentication.

## Implementing Domain-Based SSO Detection

The Logto Experience SPA automatically detects SSO requirements based on email domains. The frontend uses the `useCheckSingleSignOn` hook defined in [`packages/experience/src/hooks/use-check-single-sign-on.ts`](https://github.com/logto-io/logto/blob/main/packages/experience/src/hooks/use-check-single-sign-on.ts) to query the backend and initiate the flow.

```typescript
import { useEffect } from 'react';
import useCheckSingleSignOn from '@/hooks/use-check-single-sign-on';

export default function SignIn() {
  const { startSingleSignOn } = useCheckSingleSignOn();

  const handleEmailSubmit = async (email: string) => {
    // Contacts GET /api/interaction/single-sign-on/connectors
    const connector = await startSingleSignOn(email);
    if (connector) {
      // Redirect to the IdP authorization URL
      window.location.href = connector.authorizationUrl;
    } else {
      // Proceed with standard password authentication
    }
  };

  return /* UI calling handleEmailSubmit on form submit */;
}

```

When a domain is marked as **SSO-only**, Logto rejects normal password sign-in attempts with the `session.sso_required` error code, forcing users through the SSO flow. This enforcement occurs in the interaction layer defined in [`packages/core/src/routes/interaction/single-sign-on.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/interaction/single-sign-on.ts).

## Processing SSO Authentication Callbacks

After the identity provider authenticates the user, Logto processes the callback at the `authentication` endpoint. The backend logic in [`packages/core/src/libraries/verification-helpers/single-sign-on.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/libraries/verification-helpers/single-sign-on.ts) performs the following steps:

1. Exchanges the authorization `code` for tokens (access token, ID token)
2. Validates the ID token and fetches userinfo from the IdP
3. Persists the federated token set if `tokenStorageEnabled` is true
4. Creates or updates the `user_sso_identities` claim with the identity data
5. Issues a Logto session and redirects back to the application

The session schema defined in [`packages/core/src/libraries/verification-helpers/single-sign-on-session.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/libraries/verification-helpers/single-sign-on-session.ts) stores the SSO identity as an array of objects containing `details`, `issuer`, and `identityId`, which downstream APIs include in issued tokens.

## Just-in-Time Provisioning and Security

Logto supports **Just-in-Time (JIT) provisioning** for enterprise SSO connectors. When a user signs in with an email domain matching a configured connector, Logto automatically provisions the user into the associated organization. This feature is documented in [`packages/schemas/CHANGELOG.md`](https://github.com/logto-io/logto/blob/main/packages/schemas/CHANGELOG.md) (lines 1040-1048) under the JIT provisioning section.

For security-sensitive deployments, you can configure email domains to require SSO exclusively. When enabled, authentication attempts using passwords for those domains are blocked at the API level, ensuring enterprise users always authenticate through the corporate identity provider.

## Summary

- **Logto stores SSO configurations** in the `sso_connectors` table and identity data in `user_sso_identities`, enabling persistent federated authentication.
- **Three interaction endpoints** (`authorization-url`, `authentication`, `connectors`) orchestrate the complete SSO flow in [`packages/core/src/routes/interaction/single-sign-on.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/interaction/single-sign-on.ts).
- **Frontend detection** uses the `useCheckSingleSignOn` hook to automatically redirect users based on email domain matching.
- **Token storage** can be enabled per-connector to cache IdP access tokens for downstream API calls without re-authentication.
- **JIT provisioning** automatically adds SSO users to organizations when they first sign in with a matching domain.
- **SSO-only domains** enforce strict identity provider authentication by rejecting password-based logins with `session.sso_required` errors.

## Frequently Asked Questions

### What identity provider protocols does Logto support for SSO?

Logto supports both **OpenID Connect (OIDC)** and **SAML** identity providers for enterprise SSO. The connector configuration in [`packages/core/src/libraries/verification-helpers/single-sign-on.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/libraries/verification-helpers/single-sign-on.ts) abstracts the protocol differences, allowing you to configure OIDC endpoints (authorization, token, userinfo) or SAML assertions through the same Management API.

### Can Logto store tokens from the external identity provider?

Yes. When creating an SSO connector, set `metadata.tokenStorageEnabled` to `true`. This persists the federated token set (access tokens, refresh tokens) in Logto's storage, allowing your applications to retrieve IdP access tokens via subsequent API calls without requiring the user to re-authenticate with the external provider.

### How does Logto handle user provisioning for SSO authentication?

Logto implements **Just-in-Time (JIT) provisioning** through the domain-matching system. When a user attempts to sign in with an email domain associated with an SSO connector (queried via `GET /api/interaction/single-sign-on/connectors`), Logto automatically provisions the user into the corresponding organization if they don't already exist, creating a seamless onboarding experience for enterprise users.

### What happens if a user tries to use a password for an SSO-only domain?

Logto enforces **email-domain guards** that reject password authentication attempts for domains marked as SSO-only. When the `useCheckSingleSignOn` hook detects a matching domain or when a password login is attempted for such domains, the API returns the `session.sso_required` error code, forcing the user to authenticate through the configured identity provider rather than traditional credentials.