Portal Community

SAML Overview in Passport

In the SAML 2.0 protocol, Passport is the Identity Provider (IdP) and your enterprise application is the Service Provider (SP). Passport authenticates the user and issues a signed SAML Assertion containing the user's identity and attributes. The SP validates this assertion and establishes a local session.

Metadata-First Configuration

Always start by exchanging metadata. Give the SP your IdP metadata URL: GET /passport/saml/metadata. Then upload the SP's metadata into Passport. This automates endpoint discovery and certificate exchange.

IdP Metadata

Passport publishes a standards-compliant SAML 2.0 metadata document. Provide this URL to your SP's administrator — most enterprise SaaS platforms accept a metadata URL directly.

GET /passport/saml/metadata
Content-Type: application/samlmetadata+xml

<?xml version="1.0"?>
<EntityDescriptor
    xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
    entityID="https://passport.bizfirst.ai/saml">
  <IDPSSODescriptor
      WantAuthnRequestsSigned="true"
      protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">

    <KeyDescriptor use="signing">
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:X509Data>
          <ds:X509Certificate>MIID...base64-encoded-cert...</ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </KeyDescriptor>

    <SingleLogoutService
        Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
        Location="https://passport.bizfirst.ai/passport/saml/slo"/>

    <SingleSignOnService
        Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
        Location="https://passport.bizfirst.ai/sso/provider/{consumerKey}"/>

    <SingleSignOnService
        Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
        Location="https://passport.bizfirst.ai/sso/provider/{consumerKey}"/>

  </IDPSSODescriptor>
</EntityDescriptor>

Entity ID and Endpoints

FieldValueNotes
Entity IDhttps://passport.bizfirst.ai/samlRegister this in your SP as the IdP entity ID
SSO URL (POST)/sso/provider/{consumerKey}HTTP POST binding — preferred for enterprise apps
SSO URL (Redirect)/sso/provider/{consumerKey}HTTP Redirect binding — used for IdP-initiated flows
SLO URL/passport/saml/sloSingle Logout endpoint
Metadata URL/passport/saml/metadataAuto-updating — include in SP configuration

Signing Certificate

Passport signs all SAML assertions with an RSA-2048 X.509 certificate. The certificate is embedded in the metadata document and is automatically used by SPs that consume the metadata URL. Certificate rotation is supported without downtime.

Certificate Rotation (Zero-Downtime)

1

Generate New Certificate

In Passport Admin, navigate to Security → Signing Certificates → Generate New. The new certificate is added to the metadata with use="signing" while the old one remains active.

2

SP Picks Up New Certificate

SPs that consume the dynamic metadata URL automatically pick up the new certificate on their next metadata refresh (typically 24 hours). For SPs with static certificate configuration, update them manually.

3

Switch Primary

After all SPs have updated, promote the new certificate to primary. Passport now signs new assertions with the new key.

4

Revoke Old Certificate

Once the rotation window has closed (typically 48 hours), revoke the old certificate. It is removed from the metadata document.

SAML Assertion Structure

A successful authentication produces a signed SAML Assertion. The structure includes:

<saml:Assertion
    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
    Version="2.0"
    IssueInstant="2026-05-25T10:00:00Z"
    ID="_unique-assertion-id">

  <saml:Issuer>https://passport.bizfirst.ai/saml</saml:Issuer>

  <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
    <!-- RSA-SHA256 signature over assertion -->
  </ds:Signature>

  <saml:Subject>
    <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
      user@example.com
    </saml:NameID>
    <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
      <saml:SubjectConfirmationData
          Recipient="https://sp.example.com/saml/acs"
          NotOnOrAfter="2026-05-25T10:05:00Z"
          InResponseTo="_original-request-id"/>
    </saml:SubjectConfirmation>
  </saml:Subject>

  <saml:Conditions NotBefore="2026-05-25T09:59:00Z"
                   NotOnOrAfter="2026-05-25T10:05:00Z">
    <saml:AudienceRestriction>
      <saml:Audience>https://sp.example.com/saml</saml:Audience>
    </saml:AudienceRestriction>
  </saml:Conditions>

  <saml:AttributeStatement>
    <saml:Attribute Name="email">
      <saml:AttributeValue>user@example.com</saml:AttributeValue>
    </saml:Attribute>
    <saml:Attribute Name="firstName">
      <saml:AttributeValue>Jane</saml:AttributeValue>
    </saml:Attribute>
    <saml:Attribute Name="lastName">
      <saml:AttributeValue>Smith</saml:AttributeValue>
    </saml:Attribute>
    <saml:Attribute Name="roles">
      <saml:AttributeValue>manager</saml:AttributeValue>
      <saml:AttributeValue>finance-user</saml:AttributeValue>
    </saml:Attribute>
  </saml:AttributeStatement>

</saml:Assertion>

NameID Formats

FormatValueUse Case
Email Addressurn:oasis:names:tc:SAML:1.1:nameid-format:emailAddressDefault — most SaaS apps expect email as NameID
Persistenturn:oasis:names:tc:SAML:2.0:nameid-format:persistentOpaque stable identifier — use when email may change
Transienturn:oasis:names:tc:SAML:2.0:nameid-format:transientSession-only identifier — new value each login
Unspecifiedurn:oasis:names:tc:SAML:1.1:nameid-format:unspecifiedPassport UserId (GUID) — for custom applications
Assertion Validity Window

SAML assertions are valid for 5 minutes by default (NotOnOrAfter). Ensure clock synchronization (NTP) between Passport and your SP. Clock skew > 60 seconds will cause assertion rejection. The validity window is configurable per consumer registration.

Single Logout (SLO)

Passport supports SAML 2.0 SLO. When a user logs out from any SP, Passport receives the SLO request and terminates all active SSO sessions for that user across all connected SPs. Each SP is notified via an SLO request, in parallel, before the Passport session is destroyed.

// SLO Request Flow
SP → POST /passport/saml/slo (LogoutRequest, signed)
Passport → validates signature, finds all active sessions for NameID
Passport → sends LogoutRequest to each connected SP (parallel)
Passport → destroys the Passport session
Passport → returns LogoutResponse to originating SP