# Single sign-on with Entra ID

Use [Microsoft Entra ID](https://entra.microsoft.com/) (formerly Azure Active
Directory) to let your team sign in to LedgerBee. You need an admin account in
LedgerBee and permission to register applications in Entra.

Setup has three steps: verify domain ownership, register the application in
Entra, and configure the connection in LedgerBee.

## Verify domain ownership

1. Go to **Settings → Workflows & access → Single sign-on** in LedgerBee, enter
   your domain under **Verified email domains**, and click **Add domain**.
2. Publish the record LedgerBee shows at your DNS provider, as a `TXT` record
   with the host `_ledgerbee-sso`.
3. Click **Check now**. The status changes to **Verified**.

Enter the host as `_ledgerbee-sso` without your domain. Azure DNS and most other
providers append the zone to whatever you type in the **Name** field.

Repeat for every email domain your team signs in with. Leave each record
published — LedgerBee re-checks them daily.

## Register the application in Entra ID

1. In the [Entra admin center](https://entra.microsoft.com/), go to
   **Applications → App registrations** and select **New registration**.
2. Name the application, for example `LedgerBee`.
3. Under **Supported account types**, select **Accounts in this organizational
   directory only**.
4. Under **Redirect URI**, select **Web** and paste the redirect URI from the
   **Identity provider** section of the LedgerBee SSO page. Use the **Copy**
   button — the value must match byte-for-byte.
5. Select **Register**.
6. Entra opens the application's **Overview** page. Copy the **Application
   (client) ID** from there. It stays visible on that page, so you can come
   back for it later.

### Create a client secret

1. Open the application, go to **Certificates & secrets → Client secrets**, and
   select **New client secret**.
2. Set a description and expiry, then select **Add**.
3. Copy the secret **Value** immediately. Entra shows it once.

Record the expiry date. When the secret expires, sign-in stops until you create
a new one and save it in LedgerBee.

### Collect the issuer URL

From the application's **Overview** page, open **Endpoints** and take the
**OpenID Connect metadata document** URL. It looks like:

```
https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration
```

The issuer is that URL without the `/.well-known/openid-configuration` suffix:

```
https://login.microsoftonline.com/<tenant-id>/v2.0
```

Use your directory's tenant ID. The `/common` and `/organizations` endpoints
declare a different issuer than the tokens they mint, and the connection check
rejects them.

### Assign users

Under **Enterprise applications → LedgerBee → Properties**, set **Assignment
required?** to **Yes**, and save.

Do this first. It is what makes the assignment list a restriction: while it is
**No** — the default — every account in the directory can sign in, and the list
under **Users and groups** grants nothing it did not already have.

Then, under **Enterprise applications → LedgerBee → Users and groups**, assign
the people who should be able to sign in. Entra now refuses the sign-in for
anyone not assigned, before LedgerBee sees it.

## Configure the connection in LedgerBee

On the SSO page, fill in **Identity provider**:

| Field | Value |
| --- | --- |
| **Issuer URL** | `https://login.microsoftonline.com/<tenant-id>/v2.0` |
| **Client ID** | The **Application (client) ID** from the Entra overview page |
| **Client secret** | The secret **Value** you copied |
| **Subject claim** | `oid` — see [Choosing the subject claim](#choosing-the-subject-claim) |

**Subject claim** lives under **Advanced settings**.

Select **Save**. Saving runs the check: LedgerBee fetches the metadata
document and confirms the issuer it declares matches what you entered.

### Choosing the subject claim

**Use `oid` on Entra.** It is the user's directory object ID: the same value in
every application in your directory, and the value Entra's default SCIM
attribute mapping sends as `externalId`.

`sub` also works, and is the right choice on most other providers. On Entra it
is pairwise — unique to this application registration — which costs you two
things:

- Deleting and re-creating the registration issues every member a new `sub`.
- A SCIM-provisioned user is then matched by work email rather than by external
  ID, which depends on the email in the token agreeing with the one SCIM sent.
  See [SCIM-provisioned users](#scim-provisioned-users).

Neither is a lockout. A member whose binding no longer matches is re-matched on
their next sign-in by work email or an email address at a verified domain, and
the binding re-points to the new value. Keep a domain verified so that path
stays open.

Changing the claim later takes the connection offline until you test again.

### SCIM-provisioned users

If you provision users with [SCIM](/guides/scim-provisioning), how they are
matched at sign-in depends on the subject claim:

| Subject claim | Matched on |
| --- | --- |
| `oid` | The `externalId` SCIM sent, directly. No email involved. |
| `sub` | Their work email, because `sub` never equals `externalId`. |

The `sub` path needs the email in the ID token to equal the work email SCIM
sent. Entra populates the `email` claim only when the user has a mail attribute
or you configure it as an optional claim; otherwise LedgerBee falls back to
`preferred_username`, which is the UPN. In a directory where a user's UPN and
mail differ, that match fails and the sign-in is refused.

Use `oid`, or add `email` as an optional claim on the application and make sure
every user has a mail attribute.

## Check the connection

Saving reads Entra's metadata and presents your
client credentials to it. When Entra accepts them, the connection is live.

Assign the application to the users or groups who should sign in — the check
confirms your credentials, not who Entra admits.

## Sign in

Members reach the connection through the login URL shown on the SSO page. Add it
to the LedgerBee tile in your Entra app catalogue so it appears in your team's
My Apps portal.

If the check fails, or a member's first sign-in does, see [Troubleshoot SSO](/guides/sso/troubleshooting).
