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

# Enterprise SSO: Microsoft Entra ID and LDAP

> Connect Quixa to Microsoft Entra ID (single-tenant OIDC with PKCE) or on-premise Active Directory over LDAPS / StartTLS, map groups to roles and keep a break-glass administrator.

# Enterprise SSO: Microsoft Entra ID and LDAP

Quixa signs users in with **Microsoft Entra ID** (OpenID Connect, authorization code flow with PKCE) and with **LDAP / Active Directory** (LDAPS or StartTLS). Both are configured in the Backoffice under **Enterprise SSO & Directory Services**; no configuration files or restarts are needed.

> [!NOTE]
>
> A **platform administrator** edits the global configuration and can switch to any tenant with the **Configuration scope** selector. A **tenant administrator** only sees and edits the configuration of their own tenant.

## How sign-in decides what to do

```mermaid theme={null}
flowchart TD
    A[User signs in] --> B{Known local account<br/>with a Quixa password?}
    B -- yes --> C{SSO enforced?<br/>AllowLocalFallback = off}
    C -- no --> D[Check Quixa password]
    C -- yes --> E{Break-glass account?<br/>local PlatformAdmin}
    E -- yes --> D
    E -- no --> F[Refused: use company sign-in]
    B -- no --> G{LDAP enabled?}
    G -- yes --> H[Bind against the directory]
    H --> I[Link or provision the user<br/>and sync the role]
    G -- no --> J[Refused]
```

* A local password is **never** sent to the directory, and a local account is never converted into a directory account.
* Directory accounts (LDAP or Entra ID) cannot use a Quixa password, and **Forgot password** does not send them a reset code.

## Microsoft Entra ID

### 1. Create a single-tenant App Registration

1. In the Entra admin center open **App registrations → New registration**.
2. **Supported account types**: *Accounts in this organizational directory only (single tenant)*. Quixa refuses `common`, `organizations` and `consumers`; it needs your **Directory (tenant) ID** GUID.
3. **Redirect URI**: platform **Web**, value `https://quixa.example.com/auth/callback/entra` (your Quixa address followed by `/auth/callback/entra`).
4. Under **Certificates & secrets** create a client secret and copy its **Value**.
5. Copy the **Application (client) ID** and the **Directory (tenant) ID** from the overview page.

### 2. Allow only assigned users

Open **Enterprise applications → (your app) → Properties** and set **Assignment required?** to **Yes**. Then assign the users or groups that may use Quixa under **Users and groups**. Everyone else is stopped by Microsoft before reaching Quixa.

### 3. Send roles or groups

Pick one of the two:

* **App roles (recommended)**: under **App roles** create roles such as `Quixa.Admin` and `Quixa.Developer`, assign them to groups in the enterprise application, and map the role values in Quixa.
* **Groups**: under **Token configuration → Add groups claim** choose *Security groups* (or *Groups assigned to the application*). The token then carries group object IDs, for example `2b3c4d5e-0000-0000-0000-000000000001`; map those IDs in Quixa.

### 4. Enforce MFA with Conditional Access

Quixa does not ask for a second factor on Entra sign-ins; Microsoft does. Create a **Conditional Access** policy that targets the Quixa enterprise application, requires **multifactor authentication** (and optionally a compliant device or trusted location), and turn it on.

### 5. Configure Quixa

| Field | Example |
| - | - |
| Directory (Tenant) ID | `11111111-2222-3333-4444-555555555555` |
| Application (Client) ID | `aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee` |
| Client Secret | the secret **Value** (stored encrypted) |
| Callback Redirect URI | `https://quixa.example.com/auth/callback/entra` |
| Allowed Corporate Email Domain | `example.com` (optional) |

Click **Test OIDC Discovery** to confirm that the tenant can be reached, then **Save**.

> [!TIP]
>
> During sign-in Quixa validates the id\_token signature against your tenant's published keys and checks the issuer, the audience (your client ID), the lifetime, the tenant ID and a one-time nonce. The browser also has to return the same `state` that started the sign-in, and the code is redeemed with a PKCE verifier that never leaves the server.

### How Entra users are matched

1. By their stable object ID (`oid`) when they signed in before.
2. By email only when the existing Quixa account has **no password and no linked identity** and belongs to the tenant the configuration provisions into.
3. Otherwise a new user is created in that tenant (when auto-provisioning is on).

If the email belongs to an existing account that cannot be linked automatically, sign-in stops with *"An account with this email already exists. Ask an administrator to link it."* Local platform administrators are never linked to a directory identity.

## LDAP / Active Directory

### Encryption

| Mode | Port | Setting |
| - | - | - |
| LDAPS | 636 | **Use LDAPS** on |
| StartTLS | 389 | **Use LDAPS** off, **Use StartTLS** on |

Quixa validates the directory server certificate. If your domain controllers use a certificate from an internal CA that the Quixa server does not trust, either install that CA on the server or enter the certificate's **SHA-256** (or SHA-1) thumbprint in **Trusted certificate thumbprint (optional)**, for example `3A:1F:...:9C`. Colons and letter case do not matter.

> [!WARNING]
>
> Binds over an unencrypted connection are refused. Only for an isolated lab directory can the server operator allow them with the setting `EnterpriseIdp:AllowInsecureLdap=true`.

### Connection settings

| Field | Example |
| - | - |
| LDAP Server Host | `dc01.example.com` |
| Base DN | `DC=example,DC=com` |
| Service Bind DN | `CN=svc-quixa,OU=ServiceAccounts,DC=example,DC=com` |
| User search filter | `(&(objectClass=user)(\|(sAMAccountName={0})(mail={0})))` |

Use a read-only service account. The filter must match **exactly one** entry per user; a search that returns more than one entry is refused.

**Test Connection** and **Diagnostic User Lookup** reuse the saved bind password only for the saved host, port and bind DN. When you test a different server or account, type its password.

## Group-to-role mappings

Each rule maps a directory group (or an Entra app role / group ID) to a Quixa role. When a user matches several rules, the highest role wins; with no match the **Default Fallback Role** applies.

* An LDAP rule matches the group's full DN (`CN=Quixa-Admins,OU=Groups,DC=example,DC=com`) or exactly its common name (`Quixa-Admins` or `CN=Quixa-Admins`). It never matches part of a name: `Admin` does not match `CN=NotAdmins`.
* Tenant configurations can assign **Admin, Member, Developer, Tester** and **Viewer**. **PlatformAdmin** can only be assigned by the global configuration.

## Where new users are created

* A tenant configuration creates new users in its own tenant.
* The global configuration creates them in the **Provisioning tenant** selected by the platform administrator.
* When no tenant is selected, sign-in for unknown users is refused. Quixa never creates a tenant on its own.

## Break-glass access

Keep at least one **local platform administrator** with a strong password. When you switch off **Allow Local Account Fallback**:

* everyone signs in through Entra ID or LDAP;
* local platform administrators can still sign in with their Quixa password, so a directory or network outage cannot lock you out;
* other local accounts are refused with *"Password sign-in is disabled for this organisation."*

> [!TIP]
>
> Store the break-glass credentials in your password vault, enable two-factor authentication for the account and review its sign-ins regularly.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.