Share via

How to configure On-Behalf-Of OAuth flow so User.ReadBasic.All scope does not require admin consent

Matthew Wong 0 Reputation points
2026-03-18T17:03:52.6666667+00:00

My solution has two app regs - Client and API.

I am setting up a On-Behalf-Of OAuth flow with the goal to allow user to perform Graph User query with User.ReadBasic.All permission without requiring admin consent.

Following this guide, API app reg exposes a custom scope "Portal.ReadWrite.All" and sets Client app reg as knownClientApplication as well as preAuthorizedApplication; The custom scope is then added to the Client app reg permission list.

Client app authenticates to API using MSAL, with the "Portal.ReadWrite.All" scope. From my understanding of OBO flow, we can then exchange that MSAL token which was used to authenticate into API using this call with the assertion=<MSAL token> and scope=User.ReadBasic.All, which should return a new token with User.ReadBasic.All scope.

However when I make the call to exchange the token, I got following error indicating admin consent is required.

AADSTS65001: The user or administrator has not consented to use the application with ID '<api-app-reg-id>' named '<API App Reg Name>'. Send an interactive authorization request for this user and resource.

I then granted the consent to the enterprise application using an admin account, the call succeeded and the token has the User.ReadBasic.All scope as expected. This confirms that admin consent is indeed required to exchange the token with the scope via OBO.

My questions:

Given Delegated User.ReadBasic.All allows user consent as per documentation, is admin consent supposed to be required when using the OBO flow?

If not, what is the configuration mistake that I have made judging from above description?

If so, is there any method/workaround that could achieve my goal to allow user to perform Graph User query with User.ReadBasic.All permission without requiring admin consent?

Many thanks

Microsoft Security | Microsoft Entra | Microsoft Entra ID
0 comments No comments

2 answers

Sort by: Most helpful
  1. Rukmini 36,445 Reputation points Microsoft External Staff Moderator
    2026-03-18T18:35:29.6866667+00:00

    Hello Matthew Wong

    In OBO, the API app calls Microsoft Graph, so it must have consent for User.ReadBasic.All.

    Hence, to resolve the issue, grant admin consent

    • Go to API App Registration
    • Add delegated permission: User.ReadBasic.All
    • Click Grant admin consent

    This resolves OBO token issue.

    In OBO, admin consent is required and expected for API apps.

    If the resolution was helpful, kindly take a moment to click on 210246-screenshot-2021-12-10-121802.pngand click on Yes for was this answer helpful. And, if you have any further query do let us know.


  2. Q&A Assist
    2026-03-18T17:04:23.63+00:00
    AI generated content. This question contains an answer created with AI from Q&A Assist. Learn more

    In the Microsoft identity platform, the OAuth 2.0 On-Behalf-Of (OBO) flow always uses the .default model for downstream APIs, and that drives how consent works.

    Key points from the platform behavior:

    1. OBO requires .default for the downstream resource
      • For OBO, the middle-tier API must request scopes using the .default pattern for the downstream API, not individual delegated scopes like User.ReadBasic.All.
      • This is explicitly called out: “Its use is required in the On-Behalf-Of flow and client credentials flow.”
      • For Microsoft Graph, the middle tier should request scope=https://graph.microsoft.com/.default, not User.ReadBasic.All directly.
    2. .default uses preconfigured permissions on the calling app
      • .default means “all permissions this application has been granted for this resource,” based on the app registration’s configured API permissions and the consent already granted.
      • For Graph, that means whatever Graph delegated permissions are configured on the middle-tier API’s app registration and have been consented (user or admin, depending on the permission’s policy).
    3. Consent type is determined by the permission, not by OBO
      • Whether admin consent is required is determined by the Graph permission itself and tenant policy, not by the fact that OBO is used.
      • The OBO call will fail with AADSTS65001 if the middle-tier app does not yet have consent for the requested Graph permissions.
    4. Why admin consent was required in the scenario
      • The error message shows the middle-tier app (Customer Portal API - Build a Doc) did not yet have consent for the requested Graph resource.
      • When the OBO token request was made, Entra ID evaluated the Graph permissions configured for that app (via .default) and found that the required consent had not been granted.
      • Because the OBO flow is non-interactive (no user prompt at that point), and the permission set required admin consent in that tenant configuration, the call failed until an admin granted consent.
    5. Why user consent cannot be used at OBO time
      • In OBO, the middle-tier service is calling the token endpoint without user interaction. There is no way to show a consent screen at that moment.
      • Any user consent must be obtained earlier, during an interactive sign-in flow where the client app requests consent for itself and the middle tier using .default and known client applications.
    6. Correct pattern to avoid extra admin prompts (but not admin policy)
      • Configure the client as a known client application of the middle-tier API and use .default when the user signs in, as described in “Gaining consent for the middle-tier application.”
      • Example: scope=openid https://middle-tier-api.example.com/.default during the interactive sign-in.
      • This combined consent flow prompts the user once for:
        • Client → middle-tier API permissions, and
        • Middle-tier API → downstream APIs (like Graph) permissions.
      • However, if any of those downstream permissions (for example, certain Graph permissions) are marked as “admin consent required” in the service or by tenant policy, an admin must still grant them. OBO cannot bypass that requirement.
    7. Implications for User.ReadBasic.All
      • The platform documentation states that .default is required for OBO and that static (.default) and dynamic scopes cannot be combined.
      • Therefore, the middle-tier cannot dynamically request only User.ReadBasic.All in OBO; it must request https://graph.microsoft.com/.default and rely on the app’s preconfigured Graph permissions.
      • Whether User.ReadBasic.All can be consented by users or requires admin consent is controlled by Graph’s permission model and tenant settings. If the tenant or Graph marks it as requiring admin consent, there is no supported workaround in OBO to avoid admin consent.

    Summary:

    • OBO itself does not inherently force admin consent, but it requires .default, which uses preconfigured permissions on the middle-tier app.
    • If those permissions (such as Graph’s User.ReadBasic.All via .default) require admin consent in the tenant, the OBO token request will fail until an admin grants consent.
    • There is no supported way in OBO to let users dynamically self-consent to new downstream Graph permissions at token-exchange time. The only options are:
      • Obtain combined consent up front using .default and known client applications, and
      • Have an admin grant any permissions that are admin-only in the tenant.

    References:

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.