SAML Flow ========= Overview -------- Two separate SAML integrations exist: .. list-table:: :header-rows: 1 :widths: 20 20 20 40 * - Integration - Purpose - Endpoints - Use Case * - **Site SAML** - Public/internal site access - ``/saml/*`` - Employee intranet, gated content * - **CMS SAML** - Admin CMS access - ``/saml/cms/*`` - Content editors, administrators -------------- Site SAML Flow -------------- Provides SSO for internal/external site separation. Employees access internal content; public users see external content. Architecture ~~~~~~~~~~~~ .. mermaid:: sequenceDiagram participant Browser participant App as Tafkar App participant IdP as "IdP (Entra)" Browser->>App: GET /saml/auth Note right of App: Route by domain + auth status App-->>Browser: Redirect if needed Browser->>App: GET /saml/login App-->>Browser: Redirect to IdP with AuthnRequest Browser->>IdP: AuthnRequest IdP-->>Browser: Redirect with SAMLResponse Browser->>App: POST /saml/response Browser->>App: GET /saml/logout App-->>Browser: Delete cookie, redirect to IdP Browser->>IdP: Signed LogoutRequest Login Flow ~~~~~~~~~~ .. mermaid:: flowchart TD A["User visits internal site"] --> B{"/saml/auth checks auth cookie + site access"} B -->|"Has cookie + valid group membership"| C["Allow access"] B -->|"No cookie or no access"| D["Redirect to /saml/login"] D --> E["/saml/login generates AuthnRequest — XML, Deflate, Base64, URL-encode"] E --> F["User authenticates at IdP"] F --> G["IdP POSTs to /saml/response with SAMLResponse + RelayState"] G --> H["Validate response — Decrypt RSA-OAEP with SHA1 + AES-256-CBC, check issuer, timestamps, replay"] H --> I["Create/update user, set SITE_AUTH cookie"] I --> J["Redirect to RelayState or /"] Logout Flow ~~~~~~~~~~~ .. mermaid:: flowchart TD A["User clicks logout"] --> B["/saml/logout — Create LogoutRequest XML, sign with RSA-SHA256"] B --> C{"Signing succeeded?"} C -->|"Yes"| D["Delete auth cookie"] D --> E["Redirect to IdP with signed LogoutRequest"] E --> F["IdP terminates session"] F --> G["User lands on logout-destination, external site"] C -->|"No"| H["Redirect to logout-destination without IdP logout"] Domain Routing (/saml/auth) ~~~~~~~~~~~~~~~~~~~~~~~~~~~ The ``/saml/auth`` endpoint enforces access control based on domain: .. list-table:: :header-rows: 1 :widths: 35 30 35 * - Current Domain - Auth Status - Action * - login-destination (internal) - Not authenticated - → Redirect to /saml/login * - login-destination (internal) - Authenticated - → Allow * - logout-destination (external) - Authenticated - → Redirect to internal * - logout-destination (external) - Not authenticated - → Allow -------------- CMS SAML Flow ------------- Provides SSO for CMS admin access with role-based authorization. Architecture ~~~~~~~~~~~~ .. mermaid:: sequenceDiagram participant CMS as "CMS (/cms/...)" participant IdP as "IdP (Azure AD)" CMS->>IdP: GET /saml/cms/login — AuthnRequest IdP->>CMS: POST /saml/cms/login — SAMLResponse IdP->>CMS: POST /saml/cms/logout — Logout notification Login Flow ~~~~~~~~~~ .. mermaid:: flowchart TD A["User visits CMS without session"] --> B["Redirect to GET /saml/cms/login — Create AuthnRequest with SP issuer"] B --> C["User authenticates at IdP"] C --> D["IdP POSTs to /saml/cms/login with SAMLResponse and user attributes"] D --> E["Validate response — Decrypt assertion, check issuer, timestamps, replay"] E --> F["Extract attributes — first-name, last-name, email, roles"] F --> G{"User identifier present?"} G -->|"No"| K["Redirect to login page"] G -->|"Yes"| G2{"Role attribute present?"} G2 -->|"No"| K G2 -->|"Yes"| H{"Role matches allowed roles?"} H -->|"No"| K H -->|"Yes"| I["User provisioning — Create/update user, assign CMS group"] I --> J["Set session, redirect to CMS"] Key Differences from Site SAML ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For a detailed comparison of configuration differences between Site SAML and CMS SAML, see :doc:`saml_documentation` (Configuration Differences section).