Skip to content

AddMicrosoftGraph app-only flow does not honor sovereign cloud Graph base URL / scopes and appears to default to public cloud Graph in token acquisition. #3808

Description

@sachinjagdale

Microsoft.Identity.Web Library

Microsoft.Identity.Web

Microsoft.Identity.Web version

4.9.0

Web app

Sign-in users and call web APIs

Web API

Protected web APIs call downstream web APIs

Token cache serialization

In-memory caches

Description

A consumer can configure:

options.RequestAppToken = true or WithApponly
options.BaseUrl = "https://graph.microsoft.us/v1.0"
options.Scopes = new[] { "https://graph.microsoft.us/.default" }
but the underlying GraphAuthenticationProvider appears to still rely on a public cloud default, e.g. via:

https://github.com/AzureAD/microsoft-identity-web/blob/master/src/Microsoft.Identity.Web.GraphServiceClient/GraphAuthenticationProvider.cs#L95

readonly IEnumerable<string> _defaultGraphScope = ["https://graph.microsoft.com/.default"];

Expected behavior
When AddMicrosoftGraph(options => ...) is configured with:

RequestAppToken = true
custom BaseUrl
custom Scopes
then app-only token acquisition should use the configured scopes exactly as provided, including sovereign cloud Graph resources such as:

https://graph.microsoft.us/.default
https://microsoftgraph.chinacloudapi.cn/.default
and should not fall back to graph.microsoft.com.

Reproduction steps

A consumer can configure Add Microsoft graph with options

options.RequestAppToken = true or WithApponly
options.BaseUrl = "https://graph.microsoft.us/v1.0"
options.Scopes = new[] { "https://graph.microsoft.us/.default" }

Error message

Microsoft.Graph.Models.ODataErrors.ODataError: Access token validation failure. Invalid audience.\r\n at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.ThrowIfFailedResponse(HttpResponseMessage response, Dictionary2 errorMapping, Activity activityForAttributes, CancellationToken cancellationToken)\r\n at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.SendAsync[ModelType](RequestInformation requestInfo, ParsableFactory1 factory, Dictionary2 errorMapping, CancellationToken cancellationToken)\r\n at Microsoft.Kiota.Http.HttpClientLibrary.HttpClientRequestAdapter.SendAsync[ModelType](RequestInformation requestInfo, ParsableFactory1 factory, Dictionary2 errorMapping, CancellationToken cancellationToken)\r\n at Microsoft.Graph.Users.UsersRequestBuilder.GetAsync(Action1 requestConfiguration, CancellationToken cancellationToken)\r\n at GraphTestApi.Controllers.UsersController.Search(String q, String userType, Int32 top, CancellationToken ct)

Id Web logs

Logs
info: Microsoft.Identity.Web.TokenAcquisition[0]
False MSAL 4.83.1.0 MSAL.NetCore .NET 8.0.26 Microsoft Windows 10.0.26100 [2026-05-08 05:23:51Z] === Token Acquisition (ClientCredentialRequest) started:
Scopes: https://graph.microsoft.com/.default
Authority Host: login.microsoftonline.us

No response

Relevant code snippets

builder.AddMicrosoftGraph(options =>
                {
                    options.RequestAppToken = true;     // register for acquiring token with app only access as default option
                    options.BaseUrl = $"https://graph.microsoft.us/v1.0";
                    options.Scopes = new string[] { "https://graph.microsoft.us/.default" };
                });

Regression

No response

Expected behavior

Expected behavior
When AddMicrosoftGraph(options => ...) is configured with:

RequestAppToken = true
custom BaseUrl
custom Scopes
then app-only token acquisition should use the configured scopes exactly as provided, including sovereign cloud Graph resources such as:

https://graph.microsoft.us/.default
https://microsoftgraph.chinacloudapi.cn/.default
and should not fall back to graph.microsoft.com.

Metadata

Metadata

Assignees

Labels

P2bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions