singleloginsystem/SAML_SSO.md
= 57f0a4590c Feat: Add comprehensive support for SAML SSO integration
- Introduced `ddev` configuration for Laravel-based SAML SSO setup.
- Added detailed technical specifications for SAML 2.0 integration, including endpoints, flows, and cryptographic signing.
- Created extensive unit tests to validate `SamlIdpController` and `SamlIdpService` functionalities.
- Enhanced metadata generation, SAML request parsing, and cryptographic signing of responses.
- Implemented models, services, and tests to standardize IdP interactions with Service Providers.
2026-06-01 11:04:16 +00:00

7.9 KiB

SAML 2.0 SSO Integration Diagram & Specifications

This document provides a comprehensive technical reference for the SAML 2.0 Identity Provider (IdP) integration. It includes sequence diagrams, an endpoint directory, and data flow models detailing request/response payloads, service responsibilities, and cryptographic boundaries.


End-to-End SSO Authentication Flow

Below is the complete sequence diagram detailing how a user authenticates into Microsoft Teams / Outlook via this Laravel SSO Identity Provider.

sequenceDiagram
    autonumber
    actor User as User Browser
    participant MS as Microsoft Entra ID<br/>(Service Provider)
    participant IdP as Laravel SSO Portal<br/>(Identity Provider)
    participant DB as Database
%% Step 1-3: SP Redirection
    User ->> MS: 1. Access Microsoft Teams/Outlook (e.g. user@company.com)
    MS ->> MS: 2. Detect company.com is federated to Laravel SSO Portal
    MS ->> User: 3. Redirect with SAMLRequest & RelayState (HTTP-Redirect)
%% Step 4: Access SSO Endpoint
    User ->> IdP: 4. Request /saml/sso?SAMLRequest=...&RelayState=...
%% Step 5-6: Auth Check & Interception
    alt User is NOT Authenticated
        IdP ->> IdP: 5a. Save SAMLRequest & RelayState to Session
        IdP ->> User: 5b. Redirect to /login
        User ->> IdP: 5c. User inputs credentials (Fortify login)
        IdP ->> DB: 5d. Authenticate user
        IdP ->> User: 5e. Redirect to /dashboard (ResolveDashboardRouteController)
        Note over IdP, User: ResolveDashboardRouteController intercepts session,<br/>detects saml_pending_request, redirects back to /saml/sso
        User ->> IdP: 5f. Request /saml/sso (Authenticated)
    else User IS Authenticated
        Note over User, IdP: Immediately proceed to Step 6
    end

%% Step 7: Parse and Retrieve
    IdP ->> DB: 6. Match SAML Issuer (SP Entity ID) against ConnectedApps
    DB -->> IdP: Return Connected App metadata & SAML configurations
%% Step 8-11: Response Generation
    Note over IdP: App\Services\SamlIdpService<br/>1. Build SAML Response XML<br/>2. Retrieve User email & immutable_id<br/>3. Cryptographically sign Assertion node using idp.key
    IdP ->> IdP: 7. Base64 encode signed SAML XML
    IdP ->> IdP: 8. Clear SAML pending request from session
    IdP -->> User: 9. Render post_response.blade.php with hidden auto-submitting form
%% Step 12-14: Microsoft ACS Callback
    User ->> MS: 10. POST SAMLResponse & RelayState to Microsoft ACS URL
    Note over MS: 1. Validate XML Signature against IdP public certificate (idp.crt)<br/>2. Map SAML NameID claim to user's ImmutableId
    MS -->> User: 11. Grant secure access to Microsoft Teams & Outlook!

SAML 2.0 Endpoint Directory

This table maps all endpoints involved in the SAML 2.0 integration, including input values, controller and service responsibilities, and outputs.

Endpoint HTTP Method Request Inputs / Parameters Internal Service Called Core Responsibility Response Output
/saml/metadata GET None App\Services\SamlIdpService@generateMetadata Generates the IdP's official SAML 2.0 XML metadata descriptor to share signing certificates and SSO endpoints with external systems. 200 OK (XML payload)
Content-Type: application/xml
/saml/sso GET / POST SAMLRequest (base64/deflated)
RelayState (optional redirect URL)
App\Services\SamlIdpService@parseRequest
App\Services\SamlIdpService@findConnectedApp
App\Services\SamlIdpService@generateResponse
- Decodes and parses SAMLRequest.
- Matches Issuer (Entity ID) to an active SAML Connected App.
- Redirects guests to /login with session preservation.
- Intercepts authenticated sessions to build and sign SAML XML assertions.
200 OK (renders redirect view) or 302 Redirect to /login
/dashboard GET Session Cookie App\Helpers\DashboardRoute Intercepts successful post-login routing. If the session holds a pending SAML request, redirects the browser back to /saml/sso. 302 Redirect to /saml/sso (if pending) or dashboard routes

Data Mapping & Cryptographic Flow

Here is the step-by-step overview of how the Laravel Identity Provider translates local user attributes into a cryptographically signed assertion accepted by Microsoft:

[Local Database]                             [Cryptographic Signing]
User:                                        Private Key: storage/app/saml/idp.key
 ├── email: user@company.com                  Public Cert: storage/app/saml/idp.crt
 └── immutable_id: user-123-immutable                 │
       │                                              ▼
       │ (Maps to)                      ┌───────────────────────────┐
       ▼                                │ XMLSecLibs RSA-SHA256     │
┌─────────────────────────────┐         │ Signs <saml:Assertion>    │
│  SAML Assertion Claims      │────────>│ Moves <Signature> node    │
│  - NameID: persistent       │         │ before <Subject> for      │
│  - IDPEmail: user@company   │         │ schema validation.        │
│  - mail: user@company       │         └───────────────────────────┘
│  - upn: user@company        │                       │
└─────────────────────────────┘                       ▼
                                        ┌───────────────────────────┐
                                        │  Base64-encoded Payload   │
                                        │  SAMLResponse = PHNhb...  │
                                        └───────────────────────────┘

Claim & Attribute Mapping Details

Microsoft Entra ID maps the incoming assertion elements exactly to the cloud user directory:

  • saml:NameID (persistent format): Directly maps to the user's ImmutableId (configured locally in the admin panel or auto-generated deterministically as the base64-encoded user ID).
  • IDPEmail / upn claims: Map to the user's UserPrincipalName (the email address used for login inside Microsoft 365, e.g. user@company.com).