> ## Documentation Index
> Fetch the complete documentation index at: https://bruno-a6972042-mintlify-c74cb75a.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# SAML Single Sign-On (SSO) Overview

<Info>
  SAML SSO is available for Ultimate Edition customers behind a feature flag. Please contact your Bruno Account Manager to enable this feature.
</Info>

## What is SAML SSO?

SAML (Security Assertion Markup Language) Single Sign-On allows your organization to use your existing identity provider (IdP) to authenticate users accessing Bruno. With SAML SSO, Admins can login to the License Portal without an OTP code and Users can activate their licenses without a key.

## Benefits of SAML SSO with Bruno

### Centralized Authentication

* **Single set of credentials**: Admins and users access Bruno with the same credentials they use for other corporate applications
* **Streamlined access**: One-click access to Bruno through your identity provider's portal

### Enhanced Security

* **Centralized access control**: Manage Bruno access through your existing identity management system
* **Multi-factor authentication**: Leverage your IdP's MFA capabilities for Bruno access
* **Audit trail**: Track all authentication activities in your identity provider
* **Automatic session management**: Control session timeouts and security policies centrally

### Operational Efficiency

* **Simplified onboarding**: New employees automatically receive Bruno Ultimate access as part of their standard onboarding
* **Simplified offboarding**: Departing employees automatically lose Bruno Ultimate access when removed from your IdP
* **Reduced administrative overhead**: IT teams spend less time on manual user management

## Supported Identity Providers

Bruno supports SAML 2.0 SSO with the following identity providers:

* **Okta** - [Configuration Guide](./configure-saml-sso-with-okta)
* **Microsoft Entra ID (Azure AD)** - [Configuration Guide](./configure-saml-sso-with-entra-id)
* **Generic SAML 2.0 providers** - Any SAML 2.0 compliant identity provider

<Info>
  Bruno has no IdP-specific logic — it only requires a standards-compliant SAML 2.0 assertion containing the [required attributes](#required-saml-attributes). If your provider isn't listed above, follow the general setup flow below and use the [Using Groups for Access Control](#using-groups-for-access-control) section to map your existing directory groups to Bruno access levels.
</Info>

## Prerequisites

Before configuring SAML SSO, ensure you have:

* **Ultimate Edition subscription** with SAML SSO feature enabled
* **Admin access** to the Bruno License Portal (`https://license.usebruno.com/`)
* **Admin access** to your identity provider (Okta, Entra ID, etc.)

## General Setup Flow

Setting up SAML SSO involves configuration in both your identity provider and Bruno:

### 1. Configure Your Identity Provider

In your identity provider (Okta, Entra ID, etc.):

* Create a new SAML application for Bruno
* Configure the SAML settings using Bruno's ACS URL and Entity ID
* Set up attribute mappings for user information
* Configure role or group mappings for admin and user access
* Assign users or groups to the Bruno application

### 2. Configure Bruno

In the Bruno License Portal:

* Navigate to Settings → SSO
* Toggle **Enable SSO** to on
* Enter your IdP's SAML metadata (Entity IDLogin URL, Certificate)
* Configure **Role Mapping** to match your IdP's role or group attributes
* Set session timeout preferences
* Save Configuration

### 3. Test and Verify

* Test SSO login with a test user account
* Verify user attributes are correctly mapped
* Confirm role assignments work as expected
* Test session timeout behavior

## SAML Configuration Values

When configuring your identity provider, you'll need these Bruno-specific values:

| Field                        | Value                               | Notes                                                                                                                                            |
| ---------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| **ACS URL**                  | Specific to your Bruno subscription | Copy the exact SAML ACS URL from your Bruno SSO settings page. Format: `https://license.usebruno.com/api/v2/auth/sso/saml/acs/{subscription-id}` |
| **SP Issuer ID / Entity ID** | Enter a unique value                | Can be any unique identifier (e.g., `bruno`, `bruno-demo`). Must match exactly between Bruno and your IdP                                        |

<Info>
  **Important**: Always copy the ACS URL and SP Issuer ID / Entity ID directly from your Bruno SSO settings page. The Entity ID can be any unique value you choose, but it must match exactly between Bruno and your identity provider.
</Info>

## Required SAML Attributes

Bruno requires the following SAML attributes to be configured in your identity provider. These attributes are sent in the SAML assertion and used to provision and manage user access:

### User Attributes

| Attribute Name            | Description                                            | Example Value                                                                                     |
| ------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| **NameID**                | User's email address (unique identifier)               | `user.mail` or `user.email` - Must be in email format                                             |
| **roles** *or* **groups** | User role(s) or group membership(s) for access control | Any role or group value from your IdP (e.g., `BrunoAdmin`, `Bruno-Users`, `Engineering`, `admin`) |
| **fullName**              | User's full name                                       | `user.firstName+" "+user.lastName` or equivalent                                                  |

<Info>
  **Attribute Configuration Details:**

  * **NameID**: Bruno uses the NameID as the unique user identifier and email address. Configure your IdP to send the user's email address as the NameID with format `urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress`. This is critical for user identification and license activation.

  * **roles / groups**: This attribute contains the access control value(s) from your identity provider. Bruno recognizes **four** attribute names — `role`, `roles`, `group`, and `groups` (case-insensitive) — so you can send whichever your IdP produces naturally. The value can be:

    * **Group membership** from your existing directory (e.g., `Bruno-Admins`, `Engineering`) — see [Using Groups for Access Control](#using-groups-for-access-control)
    * An app role or role attribute, if your IdP has one (e.g., Entra ID App Roles, an Okta profile attribute)
    * A hardcoded constant value for testing purposes (e.g., `admin`, `user`)

    Bruno merges the values of **every** recognized attribute into a single list, so sending `roles` and `groups` together is safe — a match in either grants access.

    **Important**: The values sent in the SAML assertion must be mapped to either "Admin Roles" or "User Roles" in the Bruno License Portal's SSO Settings (see [Role Mapping](#role-mapping) section below).

  * **fullName**: This attribute should contain the user's complete name. It can be mapped to:

    * A single field if your IdP has a combined name field
    * A concatenation of first and last name fields (e.g., `user.firstName+" "+user.lastName`)
    * Any existing user property in your IdP that contains the full name

    If your IdP cannot concatenate fields, you can instead send separate **`firstName`** and **`lastName`** attributes — Bruno joins them when no `fullName` is present.
</Info>

### Using Groups for Access Control

Bruno does not require a dedicated "role" attribute. Because it accepts attributes named `role`, `roles`, `group`, or `groups`, **your existing directory groups work as-is** — there is no need to create app roles or custom user attributes just for Bruno.

<Info>
  **Which should I use?**

  * **Groups** — best if your organization already manages Bruno access through directory groups (e.g. `Bruno-Admins`, `Bruno-Users`), or if your IdP has no app-role concept at all. This is the normal path on most generic SAML 2.0 connectors.
  * **Roles** — best if your IdP has a first-class app-role primitive you already use, such as Entra ID App Roles (`user.assignedroles`) or an Okta profile attribute.
  * **Both** — fully supported. Bruno checks every recognized attribute, so you can send `roles` and `groups` in the same assertion.
</Info>

**Sending group membership from your IdP**

Most identity providers do **not** include group membership in a SAML assertion by default, and most of those that can will name the attribute something Bruno doesn't recognize. The universal rule: the attribute must arrive named `role`, `roles`, `group`, or `groups`.

| Identity provider        | Where to configure it                                                                                                          | Watch out for                                                                                                                                                                                                  |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Okta**                 | SAML Settings → **Group Attribute Statements** ([guide](./configure-saml-sso-with-okta#step-4-configure-attribute-statements)) | A Profile attribute alone does not include group names; group-assigned users need the Group Attribute Statement                                                                                                |
| **Entra ID**             | Attributes & Claims → **Add a group claim** ([guide](./configure-saml-sso-with-entra-id#step-4-configure-attributes--claims))  | Check "Customize the name of the group claim" and set it to `groups`, otherwise the claim arrives as a full URI                                                                                                |
| **Other / generic SAML** | Look for a "group attribute", "memberOf" or "group attribute statement" option in the SAML app settings                        | Many providers default the attribute name to `memberOf`, which Bruno does **not** recognize — rename it to `groups`. Also scope it to groups assigned to the Bruno app rather than the user's entire directory |

Then in **License Portal → Settings → SSO → Role Mapping**, enter the **exact group names** as your IdP emits them — for example `Bruno-Admins` under Admin Roles and `Bruno-Users` under User Roles.

**Common pitfalls with group-based access**

* **An attribute name is not a value.** Where your IdP maps "SP attribute name → IdP attribute name", the right-hand side names an attribute to *read from* — it is not a literal value to send. Pointing it at an attribute that doesn't exist produces an *empty* attribute rather than an error, and an empty attribute yields no roles, so the login is rejected with a permissions error while both sides look correctly configured.
* **URI-style attribute names don't match.** `http://schemas.microsoft.com/ws/2008/06/identity/claims/groups` is not recognized. Bruno matches the four bare names only.
* **Group names are case-sensitive.** `bruno-admins` in the assertion will not match `Bruno-Admins` in Role Mapping.
* **Some IdPs emit group IDs rather than names.** If you see opaque GUIDs in the assertion, either switch the source attribute to display names or paste the GUIDs into Role Mapping verbatim.
* **The group must be assigned to the Bruno application**, not merely exist in your directory. Most IdPs only emit groups that are scoped to the app.
* **Only the first `<AttributeStatement>` block is read.** If your IdP splits attributes across multiple statement blocks, values in later blocks are ignored.

### Example SAML Assertion

Here's an example of how these attributes appear in a SAML assertion:

```xml theme={null}
<saml2:AttributeStatement>
  <saml2:Attribute Name="roles" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
    <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
                          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                          xsi:type="xs:string">admin</saml2:AttributeValue>
  </saml2:Attribute>
  <saml2:Attribute Name="fullName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
    <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
                          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                          xsi:type="xs:string">user.firstName+" "+user.lastName</saml2:AttributeValue>
  </saml2:Attribute>
</saml2:AttributeStatement>
```

If you are using group membership instead, the equivalent assertion sends a `groups` attribute, which may carry multiple values:

```xml theme={null}
<saml2:AttributeStatement>
  <saml2:Attribute Name="groups" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
    <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
                          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                          xsi:type="xs:string">Bruno-Admins</saml2:AttributeValue>
    <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
                          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                          xsi:type="xs:string">Engineering</saml2:AttributeValue>
  </saml2:Attribute>
</saml2:AttributeStatement>
```

<Warning>
  **Watch for an attribute that is present but empty.** A value like this extracts no roles at all and results in a "You do not have necessary permissions" error, even though the attribute appears in the assertion:

  ```xml theme={null}
  <saml2:Attribute Name="roles" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
    <saml2:AttributeValue xsi:nil="true" xsi:type="xsd:string"/>
  </saml2:Attribute>
  ```

  `xsi:nil="true"` means your IdP resolved the mapping to an attribute that has no value for this user. Fix the mapping in your IdP, or remove the attribute and use group membership instead.
</Warning>

<Warning>
  **Important**: The `fullName` attribute plus at least one role or group source is required for SAML SSO to work correctly. Attribute *names* are matched case-insensitively and must be one of the names Bruno recognizes (`role`, `roles`, `group`, `groups`); the attribute *values* are matched case-sensitively against your Role Mapping configuration.
</Warning>

## Role Mapping

After configuring the `roles` or `groups` attribute in your identity provider, you need to map those values to Bruno access levels in the License Portal. Group names go in exactly the same fields as role values — Bruno makes no distinction between them.

### Configuring Role Mapping in Bruno

In the Bruno License Portal's SSO Settings, you'll find two fields under "Role Mapping":

1. **Admin Roles**: Comma-separated list of role or group values that should have admin access
   * Example: `admin,BrunoAdmin,IT-Administrators` or `Bruno-Admins`
   * Users with these roles can access the admin panel and manage licenses

2. **User Roles**: Comma-separated list of role or group values that should have user access
   * Example: `user,Engineering,Developers` or `Bruno-Users`
   * Users with these roles have standard access to Bruno

<img src="https://mintcdn.com/bruno-a6972042-mintlify-c74cb75a/y2keFn0TI-qqwsMv/images/screenshots/sso-scim-management/okta/okta-sso-11.webp?fit=max&auto=format&n=y2keFn0TI-qqwsMv&q=85&s=66fad761f680694482e4207bc761f225" alt="Bruno SAML SSO role mapping configuration showing Admin Roles and User Roles fields" width="767" height="414" data-path="images/screenshots/sso-scim-management/okta/okta-sso-11.webp" />

<Info>
  **How Role Mapping Works:**

  1. Your IdP sends the `roles` or `groups` attribute value in the SAML assertion (e.g., `Engineering`)
  2. Bruno checks if this value matches any entry in the "Admin Roles" or "User Roles" fields
  3. If it matches "Admin Roles", the user will be able to access the license portal and manage licenses
  4. If it matches "User Roles", the user will be able to activate their license with SSO but will not have license portal access
  5. If it doesn't match either, the user will be denied access

  **Example Configuration:**

  * IdP sends: `groups="Engineering"`
  * Bruno Admin Roles: `admin,BrunoAdmin`
  * Bruno User Roles: `user,Engineering,QA`
  * Result: User gets standard access (matches "Engineering" in User Roles)

  **Important Implementation Details:**

  * Role and group matching is **case-sensitive** - `admin` ≠ `Admin`
  * A user can have multiple roles or groups in the IdP; Bruno checks if **any** of them match the configured values
  * If a user matches "Admin Roles", they get admin access (even if they also match "User Roles")
  * When a user is removed from the IdP, they lose access on their next login attempt
</Info>

<Warning>
  **Important**: The role and group values are case-sensitive. Ensure the values in your IdP's `roles` or `groups` attribute match exactly with the values you configure in Bruno's Admin Roles or User Roles fields. Both fields are required and must be non-empty before SSO can be enabled.
</Warning>

<Info>
  **Admin Roles and User Roles are evaluated independently, not as a hierarchy.** Membership of an Admin Roles group does not by itself grant the license-activation flow, and membership of a User Roles group does not grant License Portal access. If the same people need both, list their group in *both* fields, or give them a group in each.
</Info>

## Just-in-Time (JIT) Provisioning

With SSO enabled, Bruno automatically provisions **standard licensed users** the first time they [activate their license via SSO in the Bruno app](/license-end-users/activate-license#activating-with-sso) — this is known as Just-in-Time (JIT) provisioning. You do not need to create these accounts in advance, and JIT provisioning works without SCIM.

<Info>
  JIT provisioning applies to users who activate their license through the **SSO** option in the Bruno app's *Activate License* screen. It does not apply to signing in to the License Portal website.
</Info>

### How JIT Provisioning Works

1. In the Bruno app's *Activate License* screen, a user selects **SSO**, enters their email, and signs in with SSO for the first time.
2. Bruno validates the SAML assertion and checks the `roles` or `groups` values against your [Role Mapping](#role-mapping).
3. If a value matches an entry in **User Roles**, Bruno automatically creates a standard licensed user account and issues them a license.
4. On subsequent logins, the existing account is reused (and reactivated if it was previously deactivated).

<Info>
  Users created through JIT provisioning appear in the License Portal's user list with **Added By: System (SSO)**, which distinguishes them from users you add manually.
</Info>

### JIT Provisioning Does Not Create Admins

JIT provisioning applies to **standard licensed users only**. It does **not** create or grant License Manager Admin access.

A user must already exist as an Admin in the License Portal before they can sign in to the License Manager with SSO. Mapping an IdP role or group to **Admin Roles** is not sufficient on its own: role mapping controls the access level of users who are *already* provisioned as Admins, but it does not automatically create the Admin account.

To provision Admins, use one of the following:

* **Add them manually** in the License Portal under **Settings → Admins**, then have the user sign in with SSO.
* **Use SCIM Admin Role Mapping** to provision Admins automatically from your identity provider. See [SCIM Provisioning](../scim-provisioning/overview).

<Warning>
  If an Admin tries to access the License Portal via SSO without first being added under **Settings → Admins** (or provisioned via SCIM), the login will fail even when their IdP role or group matches your configured Admin Roles. See the [SAML SSO troubleshooting guide](./troubleshooting#2-is-the-user-already-an-admin-in-bruno-license-portal) for details.
</Warning>

## License Activation and Access Control

### License Activation Flow

**For User Role Users:**

* [Users can activate their Bruno license using SSO](/license-end-users/activate-license#activating-with-sso)
* They receive a license key via email on first login
* They can use this key to activate Bruno on their local machine
* They do NOT have access to the License Portal

**For Admin Role Users:**

* Admins can access the License Portal to manage licenses and users
* Admins can view all users in their subscription
* Admins can manage role mappings and SSO configuration
* Admins can view subscription details and usage

### Session Management

* **Session timeout**: Configured in Bruno SSO settings (default: 1 hour / 3600 seconds)
* **Minimum timeout**: 60 seconds
* **Session cookies**: Secure, HTTP-only cookies are used for session management
* **Logout**: Users are logged out when the session expires or when they manually log out

<Info>
  **Coordination with IdP Sessions**: Bruno's session timeout is independent of your IdP's session timeout. The shorter timeout will take precedence. For example, if your IdP session expires after 30 minutes but Bruno is set to 1 hour, users will be logged out after 30 minutes.
</Info>

## Next Steps

Ready to configure SAML SSO? Choose your identity provider:

* [Configure SAML SSO with Okta](./configure-saml-sso-with-okta) - Complete setup guide for Okta
* [Configure SAML SSO with Entra ID](./configure-saml-sso-with-entra-id) - Complete setup guide for Microsoft Entra ID

Using a different SAML 2.0 provider? Follow the [General Setup Flow](#general-setup-flow) above, supply the [SAML Configuration Values](#saml-configuration-values) from your Bruno SSO settings page, and map your directory groups using [Using Groups for Access Control](#using-groups-for-access-control).

Need help? See our [Troubleshooting Guide](./troubleshooting) for common issues and solutions.
