You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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
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>
189
180
190
181
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>
192
190
193
191
---
194
192
195
193
## Step 6: Configure Token Claims (Optional)
196
194
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>
201
196
202
197
By default, Entra includes the `roles` claim when app roles are assigned. To include group memberships for team synchronization:
203
198
@@ -213,10 +208,7 @@ By default, Entra includes the `roles` claim when app roles are assigned. To inc
<imgsrc="/media/user-provisioning/attribute-to-entity-mapping.png"alt="Attribute Mappings configuration in Bifrost" />
344
348
</Frame>
345
349
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>
350
351
351
352
### Custom attribute mapping
352
353
353
354
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.
<imgsrc="/media/user-provisioning/custom-attribute-mapping.png"alt="Attribute Mappings configuration in Bifrost" />
360
358
</Frame>
361
359
362
360
#### Evaluation rules
@@ -366,9 +364,8 @@ You can also map any custom attributes to any entity (role, team or business uni
366
364
-**Claim values**: Can be strings, arrays, or nested objects. Bifrost resolves dotted paths (e.g., `realm_access.roles`).
367
365
368
366
<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.
372
369
</Note>
373
370
374
371
5. Click **Save Configuration**
@@ -410,6 +407,27 @@ You can also map any custom attributes to any entity (role, team or business uni
410
407
- Verify the Client ID is correct
411
408
- Check that the app registration is in the same tenant as your users
412
409
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.
0 commit comments