.. _SSO: ======================================= Single Sign-On ======================================= Glossary ========= .. glossary:: :sorted: Service Provider SP The local component (:term:`MEG QMS`) providing hte service and consuming authentication provided by :term:`IdP`. SSO Single Sign-On; two methods of SSO are currently supported: :term:`SAML` and :term:`LDAP`. More details in SSO setup in :ref:`SSO` section. LDAP Lightweight Directory Access Protocol; industry standard application protocol for accessing and maintaining distributed directory information services over an IP network. It is used as a centralized user database for :term:`Single sign-on `. DN Path Distinguished Name Path; A distinguished name path is a :term:`LDAP` entry that uniquely identifies and describes an entry in a :term:`LDAP` server. A distinguished name is a sequence of attributes and values. The first attribute and its value provide the entry's relative distinguished name (RDN). Every entry (user, group, :term:`OU`, computer) in :term:`LDAP` will have its own dn path. OU Organizational Unit; Containers that can be used to divide the organizational hierarchy. These can represent teams of users. An organizational unit will have its own :term:`DN Path`. SAML Security Assertion Markup Language; an open standard for exchanging authentication and authorization data between parties, in particular, between an identity provider and a service provider. Identity Provider IdP The remote component of :term:`SAML` that provides user account information. This role is often fulfilled by :term:`Azure Active Directory `, or Google. Active Directory A single sign on solution from Microsoft. Uses :term:`LDAP` method of authentication and can be self-hosted, while Azure Active Directory is cloud based and uses :term:`SAML`. SAML assertion Assertion A SAML assertion is an XML document returned by the Identity Provider to the Service Provider after authentication of the user. The assertion has a very specific structure, as defined by the SAML standard. A SAML assertion has a element which contains information about the user. It might have conditions and attributes associated with the information being conveyed. It is digitally signed and asserts that the user has been authenticated. SAML Artifact Artifact When the HTTP Artifact binding is used, the Artifact is a unique ID used by the :term:`Service Provider` (SP) and :term:`Identity Provider` (IdP) to reference a specific user session or transaction. The SP can use the Artifact to query the IdP for information about the user. SCIM System for Cross-domain Identity Management SCIM (pronounced *skim*) is an open, HTTP-based standard that automates the exchange of user identity information between identity providers (like an HR system) and service providers (like cloud applications). The case of MEG QMS, the API implements SCIM 2.0 protocol to allow :term:`SAML` :term:`IdPs ` to pre-emptively provision user accounts. This allows the accounts to be manually granted permissions, team memberships before the user logs in for the first time. .. seealso:: https://www.microsoft.com/en-us/security/business/security-101/what-is-scim https://scim.cloud/ :term:`SAML` ============== .. figure:: img/saml.png SAML login flow The :term:`IDP` container is a `test environment `_ for testing SAML integration. Include ``saml`` profile when running project using docker-compose to run SAML identity provider alongside the project:: docker-compose --profile saml up .. seealso:: Client-facing setup is documented in `Single Sign On Support `_ document. Troubleshooting steps are documented in `Single Sign On Debugging `_ documentation. Attribute Mapping ^^^^^^^^^^^^^^^^^ The SAML Identity Provider can map SAML attributes to MEG user properties through the ``attribute_map`` field. This enables automatic assignment of user properties during SSO login. Supported Mappings ------------------ institution Maps user to an institution based on attributes or email domain user level Sets user access level (institution/group) wards Assigns users to specific wards teams Places users into relevant teams Example Configuration --------------------- .. code-block:: json { "hospital": { "field": "auditor.institution_id", "map": { "cavan": 123, "dublin": 456 } }, "role": { "field": "auditor.level", "map": { "nurse": "institution", "manager": "institution_group" } }, "ward": { "field": "auditor.wards", "map": { "medical_1": [789, 1011], "surgical": [1012] } }, "department": { "field": "auditor.teams", "map": { "nursing": [55, 56], "facilities": 57 } }, "email": { "field": "auditor.institution_id", "map": { "hospital1.com": 22, "hospital2.com": 33 } } } .. note:: The attribute mapping is validated to ensure: * Only valid fields can be mapped * Values map to existing entities * Institution mapping respects IDP level restrictions * Email domains are properly formatted Logout ^^^^^^^ Some SAML setups can provide ``logout_url``. If present, logout should redirec to that url even within the :term:`client app`. This means that when user logs out from client app, and the account has a SAML link, the app should redirect to back-end logout after logging the user out from the app, to also log out from the back-end and :term:`identity provider`. MAC OS ^^^^^^ Note that on Mac OS you may need to install XML sec library:: brew install Libxmlsec1 Provisioning accounts with SCIM ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SAML provisions accounts using Just-in-time methods - provisioning happens the first time the user logs in. This means that user account does not exist until user logs in, and the first login needs to be initiated via SAML, as otherwise :term:`MEG QMS` is not aware of the account's existence. :term:`SCIM` allows the accounts to be pre-emptively created by the :term:`IdP`. It exposes APIs to create, update adn delete accounts. MEG implements the SCIM 2.0 standard for the ``/Users`` endpoint. The implementation handles the synchronization of user profiles between the Identity Provider and MEG's internal user directory. To set-up SCIM, you need to create an authentication token in MEG Dashboard. Assuming SAML is already set-up: #. Open :guilabel:`⚙️ Settings` tab #. Click :guilabel:`SAML` on the toolbar #. Click :guilabel:`➕` in the IdP row to create the token if one does not already exist #. Copy the :guilabel:`SCIM url` - use this as the base URL #. Click the clipboard icon to copy the token itself to clipoard, and paset it in the Identity Provider's SCIM client. .. seealso:: `Integrate your SCIM endpoint with the Microsoft Entra provisioning service `_ explains how to configure Entra ID (Active Directory) to use SCIM to synchronize account data via SCIM. Attribute Mapping --------------------- The following table outlines how standard SCIM 2.0 User attributes map to MEG internal properties. .. list-table:: :widths: 25 25 50 :header-rows: 1 * - SCIM Attribute - MEG Property - Notes * - ``userName`` - ``saml_user.name_id`` - **Immutable.** The unique identifier used for SAML federation. * - ``externalId`` - ``saml_user.scim_id`` - The unique ID assigned by the IdP (e.g., Azure Object ID). * - ``active`` - ``user.is_active`` - Boolean indicating if the user can log in. * - ``name.givenName`` - ``user.first_name`` - * - ``name.familyName`` - ``user.last_name`` - * - ``emails[].value`` - ``user.email`` - Only the email marked ``primary`` (or the first in the list) is synced. * - ``phoneNumbers[].value`` - ``auditor.phone_number`` - Must be a valid phone number; converted to E.164 format on save. * - ``title`` - ``auditor.title`` - * - ``displayName`` - ``auditor.display_name`` - Read-only. Supported Operations --------------------- The endpoint supports the following HTTP methods: **GET (Retrieve)** Retrieves user details. Supports pagination (via ``startIndex`` and ``count``) and filtering. * **Supported Filters:** You can filter by ``userName``, ``externalId``, ``name.givenName``, ``name.familyName``, ``emails.value``, and ``active``. **POST (Create)** Creates a new user account. * The ``userName`` must be unique within the Identity Provider. * If a user with the same email exists but is not linked to SCIM, the request may fail or require manual intervention depending on configuration. **PUT (Update)** Updates an existing user. * While SCIM defines PUT as a full replacement, MEG's implementation will preserve existing sensitive fields (like ``userName``) if they are omitted from the request payload to prevent accidental data loss. * **Restriction:** You cannot change the ``userName`` of a user that has already been linked via SAML. **PATCH (Partial Update)** Performs partial updates using SCIM Patch Operations. * Accepts a list of operations to add, replace, or remove attributes. * Commonly used by Azure AD/Entra ID for minor updates (e.g., changing a surname). **DELETE (Remove)** Performs a **soft delete**. * The user record is **not** removed from the database to preserve audit trails. * Instead, the ``active`` flag is set to ``False``, effectively revoking access to the system. Testing ^^^^^^^^ Usage ---------------- 1. Run ``docker-compose --profile saml up -d`` 2. To verify that IDP is running, you can visit: http://localhost:8080/simplesaml 3. Authenticate using IDP, by following this link: `/auth/saml/test-idp/sso/ `_ and entering credentials from the section below Login accounts ---------------- * Admin account: admin (secret) - cannot be used for SAML * User: user1 (user1pass) - Lead auditor * User: user2 (user2pass) - Junior auditor LDAP ==== The LDAP container is a test environment for testing LDAP integration. It uses OpenLDAP, and so there are some slight differences with ActiveDirectory's LDAP implementation. Include ``ldap`` profile when running project using docker-compose to run identity provider alongside the project:: docker-compose --profile ldap up -d Usage ^^^^^ 1. Run ``docker-compose --profile ldap up -d`` 2. To verify that LDAP is running, attempt to login with one of the below accounts. 3. If not using docker-compose to run the project and ldap, you will need to change the connection url of the LDAP Identity Provider in django admin to ``localhost:10389``. Login accounts ^^^^^^^^^^^^^^^ Each of the below accounts will create a junior user. * User: test (password) * User: test2 (password) * User: test3 (password) * User: test4 (password) - this user will match an existing user via it's email address to demonstrate user linking.