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

@sachinjagdale

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
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions