# Configuring SAML Applications for Enterprise SSO in Logto: The Complete Technical Guide

> Configure SAML applications for enterprise SSO in Logto. This technical guide details Logto's SAML implementation, including metadata, settings, and endpoint handling.

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

---

**Logto implements SAML-based enterprise SSO through a dedicated application type that stores configuration across three linked database records—application metadata, SAML-specific settings, and encrypted X.509 secrets—while exposing REST endpoints for SP metadata exchange and assertion handling.**

Configuring SAML applications for enterprise SSO in Logto requires navigating a multi-layered architecture that separates generic application data from protocol-specific configuration and cryptographic secrets. The logto-io/logto repository provides a complete implementation spanning schema validation guards, core libraries, and REST API endpoints to handle both SP-initiated and IdP-initiated authentication flows.

## Understanding the SAML Application Data Model

Logto treats SAML integrations as a distinct **application type** consisting of three interconnected storage layers:

1. **Application entry** – Stores common fields including `name`, `description`, and `customData` (defined in the `Applications` schema)
2. **SAML configuration** – Contains `entityId`, `acsUrl`, `attributeMapping`, `encryption` settings, and `nameIdFormat` (managed in `SamlApplicationConfigs`)
3. **SAML secrets** – Houses X.509 certificates and private keys, exposing only the public SHA-256 fingerprint while keeping private keys encrypted (see `SamlApplicationSecrets`)

These records are wired together through validation guards defined in [`packages/schemas/src/types/saml-application.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/saml-application.ts). The `samlApplicationCreateGuard` enforces that `attributeMapping` and `spMetadata` cannot be omitted separately, ensuring data integrity during creation:

```ts
// packages/schemas/src/types/saml-application.ts
export const samlApplicationCreateGuard = applicationCreateGuard
  .pick({ name: true, description: true, customData: true })
  .merge(samlAppConfigGuard.partial())
  .extend({ nameIdFormat: nameIdFormatGuard.optional().default(NameIdFormat.Persistent) });

```

The `SamlApplicationResponse` type merges generic `Applications` fields with SAML-specific configuration, producing the unified API response shape returned by Logto's endpoints.

## Core Architecture and Source Files

The SAML implementation spans four architectural layers:

| Component | Responsibility | Key Source File |
|---|---|---|
| Schema definitions | Zod guards for validation and response shapes | [`packages/schemas/src/types/saml-application.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/saml-application.ts) |
| Core library | High-level CRUD operations and session management | [`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) |
| REST routes | API endpoints for metadata and assertions | [`packages/core/src/routes/saml-application/index.ts`](https://github.com/logto-io/logto/blob/main/packages/core/src/routes/saml-application/index.ts) |
| Utilities | Callback URL generation for IdP-initiated flows | [`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 core 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 request contexts, providing a clean separation between data access and HTTP transport concerns.

## API Endpoints for SAML Lifecycle Management

The router 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) exposes the complete SAML application lifecycle through the following endpoints:

| Method | Path | Purpose |
|---|---|---|
| `POST` | `/saml-applications` | Create a new SAML application |
| `GET` | `/saml-applications/:id` | Retrieve application details including SAML config |
| `GET` | `/saml-applications/:id/metadata` | Return SP metadata XML for IdP consumption |
| `POST` | `/saml-applications/:id/callback` | Assertion consumer endpoint for SP and IdP flows |
| `PATCH` | `/saml-applications/:id` | Update existing SAML configuration |
| `DELETE` | `/saml-applications/:id` | Remove the SAML application |

### Creating a SAML Application

To provision a new SAML application, send a POST request to the `/saml-applications` endpoint with the required configuration:

```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, returning the merged application data and SAML configuration.

### Retrieving SP Metadata

After creation, retrieve the Service Provider metadata XML that your Identity Provider requires:

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

```

This returns an XML document similar to:

```xml
<EntityDescriptor entityID="https://my-company.com/saml-sp" ...>
  <SPSSODescriptor WantAssertionsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
    <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                               Location="https://my-company.com/saml-acs" index="1"/>
    ...
  </SPSSODescriptor>
</EntityDescriptor>

```

Import this XML into your IdP's SAML SP metadata configuration to establish trust.

### Handling IdP-Initiated SSO

For IdP-initiated flows, the Identity Provider POSTs SAML assertions to Logto's callback URL. This URL is generated by the `getSamlAppCallbackUrl` function 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) and follows the pattern:

```

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

```

When handling assertions programmatically, forward the SAML response to this endpoint:

```ts
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'
  })
});

```

Logto validates the assertion, decrypts the content if encryption is enabled, extracts the `NameID` according to the configured `nameIdFormat`, and establishes an authenticated session.

## Certificate Rotation and Secret Management

SAML signing certificates are managed through the `SamlApplicationSecrets` table. To rotate certificates without service interruption:

```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 API returns the new public fingerprint (SHA-256 hash) but never exposes the private key, maintaining security boundaries consistent with the implementation 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).

## Summary

Configuring SAML applications for enterprise SSO in Logto follows a structured three-phase approach:

- **Data modeling** relies on three linked records (application, config, secrets) validated through Zod guards in [`packages/schemas/src/types/saml-application.ts`](https://github.com/logto-io/logto/blob/main/packages/schemas/src/types/saml-application.ts)
- **Metadata exchange** uses the `/saml-applications/:id/metadata` endpoint to generate SP metadata for IdP consumption
- **Assertion handling** occurs through the `/saml-applications/:id/callback` endpoint, supporting both SP-initiated and IdP-initiated flows with automatic decryption and session creation

The architecture ensures that sensitive cryptographic material remains encrypted while exposing only necessary public certificates and metadata endpoints.

## Frequently Asked Questions

### How does Logto store SAML application credentials securely?

Logto stores X.509 certificates and private keys in the `SamlApplicationSecrets` table, exposing only the SHA-256 fingerprint through the API while keeping private keys encrypted at rest. When you rotate certificates via the `/secrets` endpoint, the system generates new key pairs but only returns the public fingerprint, ensuring private keys never travel over the network or appear in logs.

### 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** occurs when a user logs into the IdP directly and selects your application from their dashboard, causing the IdP to POST a SAML assertion to Logto's 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). Both flows converge at the `/callback` endpoint, but IdP-initiated requires the IdP to know the specific callback URL format.

### Can I configure attribute mapping for SAML assertions?

Yes, the `attributeMapping` field in the SAML application configuration allows you to map IdP claim URIs to Logto user attributes. When creating the application, specify mappings such as `"email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"` in the request body. Logto extracts these attributes from the SAML assertion during callback processing and associates them with the authenticated session according to the mapping defined in `SamlApplicationConfigs`.

### Where can I find integration tests for the SAML application API?

The complete request/response flow is demonstrated in [`packages/integration-tests/src/tests/api/application/saml-application.test.ts`](https://github.com/logto-io/logto/blob/main/packages/integration-tests/src/tests/api/application/saml-application.test.ts), which validates the CRUD operations, metadata generation, and assertion handling endpoints. These tests serve as executable examples of how the `/saml-applications`, `/metadata`, and `/callback` endpoints interact during real-world SSO scenarios.