---
title: "Read an organization's federated-login connection"
method: GET
path: "/v1/organizations/{organization_id}/sso"
tags: ["organizations"]
---

# Read an organization's federated-login connection

`GET /v1/organizations/{organization_id}/sso`

## Request

- Base URL: `https://api.ethiack.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.ethiack.com/v1/organizations/{organization_id}/sso`
- Auth: none declared

Read the connection.

Visible to a platform admin and to the organization's owner. Analysts and
viewers get 404 from the scoped SELECT — the facts that are genuinely public
(``require_sso``, and an enabled connection's template id) already reach them
through the unauthenticated discovery endpoint, so a grant here would add
only the provisioning policy.

**Includes the per-template SAML endpoints**, which the customer has to paste
into their own IdP and which used to be returned only by the admin-only
``POST|PUT .../sso/idp``. See :func:`_connection_response`: they are derived
from a template id the reader can already see, they are published metadata
Zitadel serves unauthenticated, and no entitlement gates this read — an
organization whose plan does not include SSO needs to be able to tell
"your plan does not cover this" apart from a server fault.

Args:
    organization_id (int): The parent organization.
    db (AsyncSession): Request-scoped session.
    context (ActiveContext): Resolved caller.

Returns:
    SsoConnectionResponse: The connection, plus the SAML URLs when it is
        knowably SAML.

## Path parameters

- `organization_id` integer, required

## Response `200`

Successful Response

- SsoConnectionResponse: An organization's connection, as an admin or its owner sees it. Wider than ``GET /auth/sso/{login_slug}``, which is unauthenticated and deliberately omits everything about what happens to *accounts*. **Carries the customer-facing SAML endpoints, which the write responses also carry.** They used to come back only from ``POST|PUT .../sso/idp``, both admin-only, so the organization owner -- who can already read this resource -- had no way to see the ACS and metadata URLs they have to paste into their own IdP. Every one of them is derived from ``zitadel_idp_id`` by ``TemplateEndpoints`` and is published, non-secret metadata that Zitadel itself serves unauthenticated, so returning them here grants no authority the reader did not already hold. The descriptions are copied verbatim from ``IdpTemplateResponse`` so the two surfaces cannot drift into describing the same URL differently. Nothing about the *provider* is echoed: no metadata document, no OIDC client id and no secret. Those are inputs, admin-only, and this is a read every owner holds.
  - `login_slug` string, required: Org-scoped entry token in the login URL.
  - `zitadel_idp_id` string, nullable: The Zitadel IdP template, or null if unpointed.
  - `enabled` boolean, required: Whether federated login is served.
  - `require_sso` boolean, required: Whether members must authenticate through the IdP.
  - `provision_on_first_login` boolean, required: Whether a first federated login may mint an account. Armed only through the provisioning workflow, which requires a DNS-proven domain; not settable here.
  - `provisioned_role` 'owner' | 'admin' | 'analyst' | 'viewer', required: Sub-role within a :data:`ActorKind.ORGANIZATION` context. Snake_case wire values are used in the DB, in JWT claims synced from Zitadel, and as components of Cerbos role strings (e.g. ``"org_admin"``). Attributes: OWNER: Full authority over the organization. ADMIN: Administrative authority below the owner. ANALYST: Read and write on engagements, findings, assets. VIEWER: Read-only.
  - `verified_at` string, date-time, nullable: When a configuration test last passed against the template now in service, or null if none has. `require_sso` cannot be set true while this is null: mandating SSO on a connection nobody has proved works locks the organization out, since its members hold no password. Re-pointing the template clears it, so a verification never outlives the thing it verified.
  - `protocol` 'saml' | 'unknown', nullable: Which protocol family the template configures, as far as Phoenix can tell. Null when the connection points at no template. `saml` when `expected_issuer` is stored -- the mint workflow refuses to record a SAML template without one, so its presence is a positive signal, and it is the same discriminator the login path keys on (`sso_jit_login._issuer_verdict`). `unknown` for a connection that is pointed but stores no issuer: that is an OIDC template, or a SAML one pointed at by `PUT .../sso/template` alone, which records no issuer -- and nothing on the row separates the two. Answering `oidc` there would be a guess, and the guess would hide the ACS and metadata URLs a SAML customer cannot finish onboarding without.
  - `acs_url` string, nullable: SAML only. The Assertion Consumer Service URL the customer must configure in their IdP. Unique to this template, which is what keeps one customer's assertions off another's connection.
  - `sp_metadata_url` string, nullable: SAML only. Zitadel's **SP** metadata for this template, for customers who prefer importing it over manual entry. Named for the direction: the request bodies' `metadata_url` is the opposite one, the customer's IdP metadata that Zitadel fetches.
  - `certificate_url` string, nullable: SAML only. Zitadel's signing certificate for this template.
  - `slo_url` string, nullable: SAML only. Single-logout endpoint for this template.

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/ethiack/apis/ethiack-api.md) - [All operations](https://skmtc.dev/ethiack/apis/ethiack-api/llms.txt) - [OpenAPI document](https://skmtc.dev/ethiack/apis/ethiack-api/revisions/4eaba89bfebf?raw)
