> ## Documentation Index
> Fetch the complete documentation index at: https://idp-docs.facesign.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# SAML request contract

> What FaceSign accepts, what it returns, and what your service provider must check before it trusts either.

## AuthnRequest

What FaceSign accepts at `https://idp.facesign.dev/api/saml/sso`.

<ParamField path="Issuer" type="string" required>
  Must exactly match a registered entityID. Unregistered issuers are rejected before anything
  else happens.
</ParamField>

<ParamField path="Destination" type="string">
  Validated against the SSO endpoint when present.
</ParamField>

<ParamField path="binding" type="HTTP-Redirect | HTTP-POST" required>
  Both are supported.
</ParamField>

<ParamField path="Signature" type="not accepted">
  Signed AuthnRequests are not supported in this release and are rejected. The metadata declares
  `WantAuthnRequestsSigned="false"`.
</ParamField>

<ParamField path="Subject / NameID" type="string" default="omitted">
  Optional, and gated. See [NameID echo](#nameid-echo) below — this is the field with the
  sharpest security consequence on the whole contract.
</ParamField>

<ParamField path="RelayState" type="string">
  Returned untouched so your SP knows where to resume.
</ParamField>

## Released attributes

Present on the assertion, on a pass only.

| Attribute                             | Values                                   | Meaning                                                     |
| ------------------------------------- | ---------------------------------------- | ----------------------------------------------------------- |
| `facesign.verdict`                    | `verified_human` \| `not_verified`       | The gate outcome                                            |
| `facesign.sessionId`                  | string                                   | Audit and correlation key                                   |
| `facesign.coercionScore`              | decimal string, 0 to 1 (lower is safer)  | Duress or coaching risk                                     |
| `facesign.deepfakeResistanceScore`    | decimal string, 0 to 1 (higher is safer) | Liveness and synthetic-face analysis                        |
| `facesign.repudiationArtifactPresent` | `"true"` \| `"false"`                    | Reserved. Currently always `"false"` — do not branch on it. |

## NameID echo

By default the assertion NameID is transient and session-scoped:

```
facesign-session:<sessionId>
```

If your AuthnRequest carries a `<Subject>` NameID, the assertion echoes that identity and format
straight back — **but only for service providers explicitly registered for it.** Any other SP
sending a `<Subject>` gets:

```json theme={null}
{
  "error": "Subject echo is not enabled for this service provider",
  "code": "subject_echo_disabled"
}
```

<Warning>
  The echo binds the assertion to the identity **you supplied**. It is not an independent
  confirmation of it. FaceSign proves a live human is present; it has no way to know that the
  person is that directory identity. Treat an echoed NameID as a correlation hint, never as proof
  of identity, and keep the directory binding on your own first factor.
</Warning>

This is why echo is off by default. An unsigned AuthnRequest is unauthenticated, so an
unguarded echo would let anyone name a victim and receive a signed assertion carrying that name.

## Denial semantics

Fail-closed. `Success` with `verified_human` is issued only for a complete session with liveness
detected and intent confirmed. Any strong deepfake signal vetoes the pass.

Every other outcome returns top-level `urn:oasis:names:tc:SAML:2.0:status:Responder` with nested
`AuthnFailed`. A refusal is status-only — no assertion at all, per SAML Core §3.2.2 — and the
Response is signed.

<Note>
  A signed denial and a missing response are different things, and your fallback policy should
  treat them differently. Today every non-pass looks the same on the wire; a more granular status
  taxonomy is not available in this release.
</Note>

## Related

<CardGroup cols={2}>
  <Card title="Validate responses" icon="shield-check" href="/validate-responses">
    The checklist your SP must run before trusting anything above.
  </Card>

  <Card title="Test the live sandbox" icon="flask-conical" href="/test-the-live-sandbox">
    Capture a real response and diff against it.
  </Card>
</CardGroup>
