Skip to content

Commit 4eb3eac

Browse files
authored
docs: clarify Entra API permission types, manifest fields, role assignment requirements, and add bulk sync troubleshooting (#3237)
## Summary Improves the Microsoft Entra setup guide to fix common configuration mistakes that cause login failures and broken bulk user sync, particularly around API permission types and role assignment requirements. ## Changes - Clarified that `openid`, `profile`, `email`, and `offline_access` must be added as **Delegated** permissions, while `User.Read`, `User.Read.All`, `GroupMember.Read.All`, `Group.Read.All`, `Application.Read.All`, and `AppRoleAssignment.ReadWrite.All` must be added as **Application** permissions. Added a warning that adding the wrong permission type causes failures even when the permission appears granted. - Added `Application.Read.All` and `AppRoleAssignment.ReadWrite.All` as required Application permissions for app-role-based bulk user sync, with an explanation of why each is needed. - Added a warning that admin consent is required for Application permissions to be effective, not just listed. - Added a warning that users **must** have a role selected when assigned to the Enterprise Application — assigning without a role causes Entra to omit the `roles` claim, resulting in login rejection. - Clarified that groups must themselves be assigned to the application with a role selected; transitive group memberships are not walked by Entra. - Corrected the manifest field name from `requestedAccessTokenVersion` to `accessTokenAcceptedVersion`. - Added `groupMembershipClaims: "ApplicationGroup"` as a recommended manifest setting to scope the `groups` claim to only groups assigned to the Bifrost application. - Added two new troubleshooting sections: one for the `Claim "roles" is not present in the token` login error and one for bulk user sync assigning Viewer instead of the mapped role. - Added a note explaining that `Application.Read.All` and `AppRoleAssignment.ReadWrite.All` are only required for app-role-based bulk sync, not for login-time role mapping. ## Type of change - [ ] Bug fix - [ ] Feature - [ ] Refactor - [x] Documentation - [ ] Chore/CI ## Affected areas - [ ] Core (Go) - [ ] Transports (HTTP) - [ ] Providers/Integrations - [ ] Plugins - [ ] UI (React) - [x] Docs ## How to test Review the rendered documentation and validate against a live Microsoft Entra app registration: 1. Follow the updated Step 5 and confirm that Delegated and Application permissions are added under their correct categories. 2. Assign a user to the Enterprise Application **with** a role selected and confirm the `roles` claim appears in the issued ID token. 3. Assign a user **without** a role and confirm login is rejected with the documented error message. 4. Run a bulk user import and confirm role mappings resolve correctly when `Application.Read.All` and `AppRoleAssignment.ReadWrite.All` are granted with admin consent. 5. Confirm the manifest field `accessTokenAcceptedVersion: 2` is accepted by Entra without error. ## Breaking changes - [ ] Yes - [x] No ## Related issues ## Security considerations The guide now explicitly calls out that Application permissions require admin consent to be effective, and recommends scoping the `groups` claim to `"ApplicationGroup"` to avoid leaking unrelated tenant-wide group memberships into tokens. ## Checklist - [ ] I read `docs/contributing/README.md` and followed the guidelines - [ ] I added/updated tests where appropriate - [x] I updated documentation where needed - [ ] I verified builds succeed (Go and UI) - [ ] I verified the CI pipeline passes locally if applicable
1 parent b1ec322 commit 4eb3eac

1 file changed

Lines changed: 93 additions & 75 deletions

File tree

docs/enterprise/setting-up-entra.mdx

Lines changed: 93 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,14 @@ Configure the registration:
3535
5. Click **Register**
3636

3737
<Tip>
38-
You can add an app icon to make the application easily recognizable. The
39-
Bifrost logo is available at:
40-
[https://www.getmaxim.ai/bifrost/bifrost-logo-only.png](https://www.getmaxim.ai/bifrost/bifrost-logo-only.png)
38+
You can add an app icon to make the application easily recognizable. The Bifrost logo is available at:
39+
[https://www.getmaxim.ai/bifrost/bifrost-logo-only.png](https://www.getmaxim.ai/bifrost/bifrost-logo-only.png)
4140
</Tip>
4241

4342
6. After registration, note down the following from the **Overview** page:
4443

4544
<Frame>
46-
<img
47-
src="/media/user-provisioning/entra-app-information.png"
48-
alt="Entra App Registration Overview"
49-
/>
45+
<img src="/media/user-provisioning/entra-app-information.png" alt="Entra App Registration Overview" />
5046
</Frame>
5147

5248
| Value | Where to Find |
@@ -59,9 +55,8 @@ Configure the registration:
5955
## Step 2: Create App Roles (Optional)
6056

6157
<Note>
62-
This step is optional. You can create custom roles if thats the preferred way.
63-
Or you can map any attribute to role/team/business unit. Role mapping is
64-
required step.
58+
This step is optional. You can create custom roles if that's the preferred way. Or you can map any attribute to role/team/business unit.
59+
Role mapping is a required step.
6560
</Note>
6661

6762
Configure roles in Entra that map to Bifrost's role hierarchy (Admin, Developer, Viewer).
@@ -71,10 +66,7 @@ Configure roles in Entra that map to Bifrost's role hierarchy (Admin, Developer,
7166
3. Create the following three roles:
7267

7368
<Frame>
74-
<img
75-
src="/media/user-provisioning/entra-create-app-roles.png"
76-
alt="Entra App Roles configuration"
77-
/>
69+
<img src="/media/user-provisioning/entra-create-app-roles.png" alt="Entra App Roles configuration" />
7870
</Frame>
7971

8072
### Viewer Role
@@ -118,10 +110,7 @@ To control which users can access Bifrost, enable assignment requirement on the
118110
3. Go to **Properties**
119111

120112
<Frame>
121-
<img
122-
src="/media/user-provisioning/entra-enable-assignment.png"
123-
alt="Entra Enterprise Application Properties"
124-
/>
113+
<img src="/media/user-provisioning/entra-enable-assignment.png" alt="Entra Enterprise Application Properties" />
125114
</Frame>
126115

127116
4. Set **Assignment required?** to **Yes**
@@ -139,10 +128,7 @@ Bifrost requires a client secret for OAuth authentication.
139128
3. Click **New client secret**
140129

141130
<Frame>
142-
<img
143-
src="/media/user-provisioning/entra-create-client-secret.png"
144-
alt="Entra Enterprise Client Secrets"
145-
/>
131+
<img src="/media/user-provisioning/entra-create-client-secret.png" alt="Entra Enterprise Client Secrets" />
146132
</Frame>
147133

148134
| Field | Value |
@@ -153,10 +139,7 @@ Bifrost requires a client secret for OAuth authentication.
153139
4. Click **Add**
154140
5. **Copy the secret value immediately** - it won't be shown again!
155141

156-
<Warning>
157-
Store the client secret securely. You'll need it for the Bifrost
158-
configuration.
159-
</Warning>
142+
<Warning>Store the client secret securely. You'll need it for the Bifrost configuration.</Warning>
160143

161144
---
162145

@@ -165,39 +148,51 @@ Bifrost requires a client secret for OAuth authentication.
165148
Ensure your application has the necessary permissions.
166149

167150
<Frame>
168-
<img
169-
src="/media/user-provisioning/entra-api-permissions.png"
170-
alt="Entra Enterprise API Permissions"
171-
/>
151+
<img src="/media/user-provisioning/entra-api-permissions.png" alt="Entra Enterprise API Permissions" />
172152
</Frame>
173153

174154
1. In your app registration, go to **API permissions**
175155
2. Click **Add a permission**
176156
3. Select **Microsoft Graph**
177-
4. Choose **Application permissions**
178-
5. Add the following permissions:
157+
4. Choose the permission type as indicated in the next steps
158+
5. Add the following **Delegated** permissions (Add a permission → Microsoft Graph → **Delegated permissions**):
179159
- `openid`
180160
- `profile`
181161
- `email`
182162
- `offline_access` (for refresh tokens)
183-
184-
6. In addition to above roles, following 4 roles are required
185163
- `User.Read`
164+
165+
6. Add the following **Application** permissions (Add a permission → Microsoft Graph → **Application permissions**):
186166
- `User.Read.All`
187167
- `GroupMember.Read.All`
188168
- `Group.Read.All`
169+
- `Application.Read.All` — required for syncing app-role-based role mappings during user import
170+
- `AppRoleAssignment.ReadWrite.All` — required to read each user's app role assignments via Microsoft Graph
171+
172+
<Warning>
173+
Permission **type** matters: `openid`, `profile`, `email`, `offline_access`,
174+
and `User.Read` must be **Delegated**, while `User.Read.All`,
175+
`GroupMember.Read.All`, `Group.Read.All`, `Application.Read.All`, and
176+
`AppRoleAssignment.ReadWrite.All` must be **Application**. The same name can
177+
exist under both types — adding the wrong one will cause sign-in or sync
178+
failures even though the permission appears granted.
179+
</Warning>
189180

190181
7. Click **Add permissions**
191-
8. If required by your organization, click **Grant admin consent for [Your Organization]**
182+
8. Click **Grant admin consent for [Your Organization]** (this is required — without admin consent, Application permissions are not effective even though they appear in the list)
183+
184+
<Note>
185+
`Application.Read.All` and `AppRoleAssignment.ReadWrite.All` are only needed if you plan to use **app role based role mappings** (i.e.
186+
mappings whose attribute is `roles`) during the bulk user sync. Login-time role mapping works from the JWT alone, but bulk sync from
187+
Microsoft Graph needs these permissions to read each user's app-role assignments and resolve them to their role values (e.g. `admin`,
188+
`developer`).
189+
</Note>
192190

193191
---
194192

195193
## Step 6: Configure Token Claims (Optional)
196194

197-
<Note>
198-
Groups and other attributes are required in the claim when you configure their
199-
mapping in Bifrost.
200-
</Note>
195+
<Note>Groups and other attributes are required in the claim when you configure their mapping in Bifrost.</Note>
201196

202197
By default, Entra includes the `roles` claim when app roles are assigned. To include group memberships for team synchronization:
203198

@@ -213,10 +208,7 @@ By default, Entra includes the `roles` claim when app roles are assigned. To inc
213208
## Step 7: Assign Users and Roles
214209

215210
<Frame>
216-
<img
217-
src="/media/user-provisioning/entra-user-assignments.png"
218-
alt="Entra User Assignments"
219-
/>
211+
<img src="/media/user-provisioning/entra-user-assignments.png" alt="Entra User Assignments" />
220212
</Frame>
221213

222214
1. Go to **Enterprise applications****Bifrost Enterprise**
@@ -226,29 +218,35 @@ By default, Entra includes the `roles` claim when app roles are assigned. To inc
226218
5. Select the appropriate role (Admin, Developer, or Viewer)
227219
6. Click **Assign**
228220

221+
<Warning>
222+
You **must** select a role when assigning a user or group. Adding a user to the application without picking a role causes Entra to omit
223+
the `roles` claim from the issued ID token, and login will be rejected with `Claim "roles" is not present in the token`. If you don't want
224+
to use app roles, configure your Bifrost role mappings on the `groups` attribute instead (see [Attribute Mappings](#attribute-mappings)
225+
below).
226+
</Warning>
227+
229228
<Tip>
230-
You can assign roles to groups for easier management. All users in a group
231-
will inherit the assigned role.
229+
You can assign roles to groups for easier management. All users in a group will inherit the assigned role. The group itself must be added
230+
as an assignment with a role selected — adding users to a group that isn't assigned to the application will not propagate roles.
232231
</Tip>
233232

234233
---
235234

236235
## Step 8: Configure App Manifest
237236

238237
<Frame>
239-
<img
240-
src="/media/user-provisioning/entra-app-manifest.png"
241-
alt="Microsoft entra app manifest"
242-
/>
238+
<img src="/media/user-provisioning/entra-app-manifest.png" alt="Microsoft entra app manifest" />
243239
</Frame>
244240

245-
You will need to make 2 changes in the app manifest
241+
You will need to make the following changes in the app manifest.
242+
243+
Set the access token version to v2:
246244

247245
```json
248-
"requestedAccessTokenVersion": 2
246+
"accessTokenAcceptedVersion": 2
249247
```
250248

251-
and
249+
Add the optional `roles` and `groups` claims to the ID token:
252250

253251
```json
254252
"optionalClaims": {
@@ -271,17 +269,29 @@ and
271269
}
272270
```
273271

272+
Restrict the `groups` claim to groups assigned to this application (recommended):
273+
274+
```json
275+
"groupMembershipClaims": "ApplicationGroup"
276+
```
277+
278+
<Note>
279+
Setting `groupMembershipClaims` to `"ApplicationGroup"` ensures the `groups`
280+
claim only contains groups that are explicitly assigned to the Bifrost
281+
Enterprise application — not every group the user belongs to tenant-wide.
282+
This keeps your team and role mappings predictable and avoids leaking
283+
unrelated group memberships into the token. Use `"SecurityGroup"` or
284+
`"All"` only if you intentionally want broader group visibility.
285+
</Note>
286+
274287
## Step 9: Configure Bifrost
275288

276289
Now configure Bifrost to use Microsoft Entra as the identity provider.
277290

278291
### Using the Bifrost UI
279292

280293
<Frame>
281-
<img
282-
src="/media/user-provisioning/entra-form.png"
283-
alt="Create token dialog in Entra"
284-
/>
294+
<img src="/media/user-provisioning/entra-form.png" alt="Create token dialog in Entra" />
285295
</Frame>
286296

287297
1. Navigate to **Governance****User Provisioning** in your Bifrost dashboard
@@ -300,10 +310,7 @@ Now configure Bifrost to use Microsoft Entra as the identity provider.
300310
6. Toggle **Enabled** to activate the provider
301311
7. Click **Save Configuration**
302312

303-
<Warning>
304-
After saving, you'll need to restart your Bifrost server for the changes to
305-
take effect.
306-
</Warning>
313+
<Warning>After saving, you'll need to restart your Bifrost server for the changes to take effect.</Warning>
307314

308315
### Configuration Reference
309316

@@ -337,26 +344,17 @@ To configure attribute mappings:
337344
4. Repeat for each rule you need
338345

339346
<Frame>
340-
<img
341-
src="/media/user-provisioning/attribute-to-entity-mapping.png"
342-
alt="Attribute Mappings configuration in Bifrost"
343-
/>
347+
<img src="/media/user-provisioning/attribute-to-entity-mapping.png" alt="Attribute Mappings configuration in Bifrost" />
344348
</Frame>
345349

346-
<Note>
347-
When you mark value as "*" - the claim value is mapped as is to the entity
348-
name. Values comparisons are case-insensitive.
349-
</Note>
350+
<Note>When you mark value as "*" - the claim value is mapped as is to the entity name. Values comparisons are case-insensitive.</Note>
350351

351352
### Custom attribute mapping
352353

353354
You can also map any custom attributes to any entity (role, team or business unit). Make sure these are configured to send back to Bifrost in token configuration.
354355

355356
<Frame>
356-
<img
357-
src="/media/user-provisioning/custom-attribute-mapping.png"
358-
alt="Attribute Mappings configuration in Bifrost"
359-
/>
357+
<img src="/media/user-provisioning/custom-attribute-mapping.png" alt="Attribute Mappings configuration in Bifrost" />
360358
</Frame>
361359

362360
#### Evaluation rules
@@ -366,9 +364,8 @@ You can also map any custom attributes to any entity (role, team or business uni
366364
- **Claim values**: Can be strings, arrays, or nested objects. Bifrost resolves dotted paths (e.g., `realm_access.roles`).
367365

368366
<Note>
369-
If a user matches multiple role mapping rules, the highest privilege role is
370-
assigned. If no mapping matches, the first user to sign in receives the
371-
**Admin** role, and subsequent users receive the **Viewer** role.
367+
If a user matches multiple role mapping rules, the highest privilege role is assigned. If no mapping matches, the first user to sign in
368+
receives the **Admin** role, and subsequent users receive the **Viewer** role.
372369
</Note>
373370

374371
5. Click **Save Configuration**
@@ -410,6 +407,27 @@ You can also map any custom attributes to any entity (role, team or business uni
410407
- Verify the Client ID is correct
411408
- Check that the app registration is in the same tenant as your users
412409

410+
### `Claim "roles" is not present in the token` on login
411+
412+
This means the user signed in successfully but Entra did not emit a `roles` claim in the ID token. Bifrost rejects the login because none of your role mappings can be evaluated.
413+
414+
Causes and fixes:
415+
416+
- **User isn't assigned to a role at the Enterprise Application level.** Go to **Enterprise applications → Bifrost Enterprise → Users and groups**, edit the assignment, and pick a role (admin/developer/viewer). Adding a user to the app without selecting a role does not emit the `roles` claim.
417+
- **Role assignment is via a group that isn't itself assigned to the app.** The group needs to appear in _Users and groups_ with a role selected — Entra does not walk transitive group memberships to populate `roles`.
418+
- **Optional `roles` claim missing from the manifest.** Confirm Step 8 (App Manifest) lists `roles` under `optionalClaims.idToken`.
419+
- **Sign out and back in.** Existing sessions still carry the old token without `roles`.
420+
421+
If you don't want to use app roles at all, switch your Bifrost mappings to use the `groups` attribute (which is already in the token) instead of `roles`. See [Attribute Mappings](#attribute-mappings).
422+
423+
### Bulk user sync assigns Viewer instead of the mapped role
424+
425+
If users come in via **User Provisioning → Import users** and end up on the default role (Viewer) despite having a matching app-role-based mapping configured:
426+
427+
- Confirm the user actually has the app role assigned in Entra (**Enterprise applications → Bifrost Enterprise → Users and groups**).
428+
- Confirm both `Application.Read.All` and `AppRoleAssignment.ReadWrite.All` are granted **with admin consent** in Step 5. Without these, Bifrost cannot read the app role catalog or per-user assignments via Microsoft Graph, so the synthetic `roles` claim used by the importer will be empty.
429+
- Server logs will contain `[ENTRA-ROLES] failed to fetch app role catalog: ... 403` if the permission is missing.
430+
413431
---
414432

415433
## Next Steps

0 commit comments

Comments
 (0)