# How to Configure Enterprise SSO with SAML in Logto: A Complete Technical Guide

> Configure enterprise SSO with SAML in Logto using the REST API, expose SP metadata to your IdP, and handle SAML assertions. This guide simplifies SAML integration.

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

---

**To configure enterprise SSO with SAML in Logto, create a SAML application via the REST API, expose the SP metadata to your Identity Provider (IdP), and handle SAML assertions through the callback endpoint.**

Logto treats SAML-based integrations as a distinct application type within its open-source identity infrastructure. When you configure enterprise SSO with SAML in Logto, the system stores three interconnected records—application metadata, SAML configuration, and cryptographic secrets—managed through type-safe schemas and core libraries.

## Understanding Logto's SAML Application Architecture

Logto's SAML implementation separates concerns across schema definitions, core libraries, and route handlers. Understanding this architecture ensures you configure the integration correctly.

### Data Model and Schema Definitions

The data contract for SAML applications resides in [`packages/schemas/src/types/saml-application.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/saml-application.ts). When you create a SAML application, Logto validates the payload against the `samlApplicationCreateGuard`, which extends the base application schema with SAML-specific fields.

The guard enforces that **attribute mapping** and **SP metadata** cannot be omitted separately during creation. The stored configuration includes:

- **entityId**: Unique identifier for your service provider
- **acsUrl**: Assertion Consumer Service URL where Logto receives SAML responses
- **attributeMapping**: Maps IdP claims to Logto user attributes
- **encryption**: Configuration for assertion encryption
- **nameIdFormat**: Format for the NameID (defaults to `Persistent`)

### Core Library Implementation

All CRUD operations and session handling logic are encapsulated in [`packages/core/src/libraries/saml-application/saml-applications.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/libraries/saml-application/saml-applications.ts). This library is instantiated in [`packages/core/src/tenants/Libraries.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/tenants/Libraries.ts) and injected into the request context, providing a clean separation between HTTP transport and business logic.

## Step-by-Step Configuration Process

### Step 1: Create the SAML Application

Use the `/saml-applications` endpoint to instantiate the integration. The request must include the required SAML configuration fields alongside basic application metadata.

```bash
curl -X POST https://<tenant>.logto.io/api/saml-applications \
  -H "Authorization: Bearer <admin-access-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My SAML App",
    "description": "Enterprise SSO integration",
    "entityId": "https://my-company.com/saml-sp",
    "acsUrl": "https://my-company.com/saml-acs",
    "attributeMapping": {
      "email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
      "name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"
    },
    "encryption": {
      "enabled": false
    },
    "nameIdFormat": "persistent"
  }'

```

The response conforms to the `SamlApplicationResponse` type defined in the schema, returning the application ID and configuration details.

### Step 2: Retrieve and Configure SP Metadata

After creation, export the Service Provider metadata by calling the metadata endpoint defined in [`packages/core/src/routes/saml-application/index.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/saml-application/index.ts).

```bash
curl -X GET https://<tenant>.logto.io/api/saml-applications/<app-id>/metadata \
  -H "Authorization: Bearer <admin-access-token>"

```

Logto generates an XML document containing the **EntityDescriptor**, **SPSSODescriptor**, and **AssertionConsumerService** endpoint. Import this XML into your IdP's configuration interface to establish trust. The metadata includes the public signing certificate fingerprint, while the private key remains secured in the `SamlApplicationSecrets` store.

### Step 3: Handle SAML Assertions and Callbacks

The callback endpoint (`POST /saml-applications/:id/callback`) handles both SP-initiated and IdP-initiated flows. Located in [`packages/core/src/routes/saml-application/index.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/saml-application/index.ts), this endpoint validates incoming SAML requests, decrypts assertions if encryption is enabled, and creates authenticated Logto sessions.

For IdP-initiated SSO, the IdP posts directly to the callback URL. For programmatic handling:

```typescript
import fetch from 'node-fetch';

await fetch(`https://<tenant>.logto.io/api/saml-applications/${appId}/callback`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    SAMLResponse: '<base64-encoded-assertion>',
    RelayState: 'optional-state'
  })
});

```

## Implementing SP-Initiated vs IdP-Initiated SSO

### SP-Initiated Flow

In a Service Provider-initiated flow, the user starts at your application and is redirected to Logto. Logto then generates a SAML request to the IdP. The user authenticates with the IdP, and the IdP redirects back to Logto's **ACS URL** with a SAML assertion.

### IdP-Initiated Flow

For Identity Provider-initiated flows, the user starts at the IdP portal. The IdP posts a SAML request to the callback URL generated by `getSamlAppCallbackUrl` in [`packages/core/src/saml-application/SamlApplication/utils.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/saml-application/SamlApplication/utils.ts). The URL structure follows:

```

https://<tenant>.logto.io/api/saml-applications/<app-id>/callback

```

Logto validates the request according to the configured `nameIdFormat`, extracts the **NameID**, and establishes a session that downstream applications can consume.

## Security Best Practices and Certificate Management

Rotate SAML signing certificates periodically using the secrets endpoint. Logto never exposes private keys in API responses; only the public **SHA-256 fingerprint** is returned.

```bash
curl -X POST https://<tenant>.logto.io/api/saml-applications/<app-id>/secrets \
  -H "Authorization: Bearer <admin-access-token>" \
  -H "Content-Type: application/json" \
  -d '{"lifeSpanInYears": 5}'

```

The `SamlApplicationSecrets` table stores X.509 certificates and private keys separately from the configuration data, ensuring cryptographic material is isolated from application metadata.

## Summary

- **SAML applications** in Logto comprise three records: application metadata, SAML configuration, and cryptographic secrets.
- **Schema validation** occurs in [`packages/schemas/src/types/saml-application.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/saml-application.ts), enforcing data integrity for entity IDs, ACS URLs, and attribute mappings.
- **REST API endpoints** at `/saml-applications` handle CRUD operations, while `/saml-applications/:id/metadata` exposes SP metadata for IdP configuration.
- **Callback handling** supports both SP-initiated and IdP-initiated flows through the `/saml-applications/:id/callback` endpoint.
- **Certificate rotation** is managed via the secrets API, with private keys never exposed in responses.

## Frequently Asked Questions

### How does Logto store SAML application secrets?

Logto stores SAML secrets in a dedicated `SamlApplicationSecrets` table separate from the configuration data. According to the source code in [`packages/schemas/src/types/saml-application.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/saml-application.ts), X.509 certificates and private keys are persisted with only the public SHA-256 fingerprint exposed through the API. The private key never leaves the server, ensuring cryptographic security even if the API is compromised.

### What is the difference between SP-initiated and IdP-initiated SSO in Logto?

**SP-initiated SSO** begins when a user clicks "Log in with SAML" on your application, triggering Logto to send an authentication request to the IdP. **IdP-initiated SSO** begins when the user logs into the IdP portal first, and the IdP posts a SAML assertion to Logto's callback URL at `https://<tenant>.logto.io/api/saml-applications/<app-id>/callback`. Both flows are handled by the same callback endpoint, but the IdP-initiated flow requires the IdP to know the callback URL generated by the `getSamlAppCallbackUrl` utility.

### Can I customize the attribute mapping between the IdP and Logto?

Yes, Logto supports customizable attribute mapping through the `attributeMapping` field in the SAML application configuration. When creating or updating the application via the REST API, you can map IdP claim URNs to Logto user attributes such as email, name, and custom data. The `samlApplicationCreateGuard` in the schema validates that attribute mappings conform to the expected structure before persistence.

### How do I rotate SAML signing certificates without downtime?

To rotate certificates, POST to the `/saml-applications/<app-id>/secrets` endpoint with the desired lifespan. Logto generates a new key pair and returns the new public fingerprint. Update your IdP configuration with the new certificate while keeping the old one active during the transition period. Once the IdP confirms the new certificate works, you can safely remove the old secret from the configuration.