MSAL.NET设备码流请求Graph令牌报AADSTS70011 scope无效错误
问题说明
本问题并非AADSTS70011: The provided value for the input parameter 'scope' is not valid相关问题的重复,已有公开方案无法解决本次故障。
复现代码(C# 设备码流认证)
基于Microsoft.Identity.Client库实现设备码流认证的代码如下:
using Microsoft.Identity.Client; var tenantId = "common"; var clientId = "475c75f3-9fdc-4d23-8956-104342a43740"; var apiUrl = "https://graph.microsoft.com"; var app = PublicClientApplicationBuilder.CreateWithApplicationOptions( new PublicClientApplicationOptions{ TenantId="common", ClientId=clientId } ) .WithRedirectUri("http://localhost") .Build(); string[] scopes = new string[] {$"{apiUrl}/.default"}; var result = await app.AcquireTokenWithDeviceCode( scopes, deviceCodeResult => { Console.WriteLine(deviceCodeResult.Message); return Task.FromResult(0); } ).ExecuteAsync(); Console.WriteLine(result.AccessToken);
执行代码抛出如下异常:
Unhandled exception. MSAL.NetCore.4.44.0.0.MsalServiceException: ErrorCode: invalid_scope Microsoft.Identity.Client.MsalServiceException: AADSTS70011: The provided value for the input parameter 'scope' is not valid. One or more scopes in 'https://graph.microsoft.com/.default offline_access profile openid' are not compatible with each other. Trace ID: 977837bb-49bb-448a-990f-f640ee518500 Correlation ID: f6483ab1-e0be-43b0-8859-086b28ac6ea2 Timestamp: 2022-06-12 00:26:35Z at Microsoft.Identity.Client.OAuth2.OAuth2Client.ThrowServerException(HttpResponse response, RequestContext requestContext) at Microsoft.Identity.Client.OAuth2.OAuth2Client.CreateResponse[T](HttpResponse response, RequestContext requestContext) at Microsoft.Identity.Client.OAuth2.OAuth2Client.ExecuteRequestAsync[T](Uri endPoint, HttpMethod method, RequestContext requestContext, Boolean expectErrorsOn200OK, Boolean addCommonHeaders, Func`2 onBeforePostRequestData) at Microsoft.Identity.Client.OAuth2.OAuth2Client.GetTokenAsync(Uri endPoint, RequestContext requestContext, Boolean addCommonHeaders, Func`2 onBeforePostRequestHandler) at Microsoft.Identity.Client.OAuth2.TokenClient.SendHttpAndClearTelemetryAsync(String tokenEndpoint, ICoreLogger logger) at Microsoft.Identity.Client.OAuth2.TokenClient.SendHttpAndClearTelemetryAsync(String tokenEndpoint, ICoreLogger logger) at Microsoft.Identity.Client.OAuth2.TokenClient.SendTokenRequestAsync(IDictionary`2 additionalBodyParameters, String scopeOverride, String tokenEndpointOverride, CancellationToken cancellationToken) at Microsoft.Identity.Client.Internal.Requests.DeviceCodeRequest.WaitForTokenResponseAsync(DeviceCodeResult deviceCodeResult, CancellationToken cancellationToken) at Microsoft.Identity.Client.Internal.Requests.DeviceCodeRequest.WaitForTokenResponseAsync(DeviceCodeResult deviceCodeResult, CancellationToken cancellationToken) at Microsoft.Identity.Client.Internal.Requests.DeviceCodeRequest.ExecuteAsync(CancellationToken cancellationToken) at Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(CancellationToken cancellationToken) at Microsoft.Identity.Client.ApiConfig.Executors.PublicClientExecutor.ExecuteAsync(AcquireTokenCommonParameters commonParameters, AcquireTokenWithDeviceCodeParameters deviceCodeParameters, CancellationToken cancellationToken) at Program.<Main>$(String[] args) in /home/adrian/azure/Program.cs:line 16 at Program.<Main>(String[] args) StatusCode: 400
复现验证(Bash脚本)
参考微软官方OAuth2.0设备码流文档的测试脚本,最初指定scope为user.read openid profile时可正常获取令牌调用Graph接口;将scope替换为URL编码后的https://graph.microsoft.com/.default后,同样返回invalid_scope错误,提示scope集合存在互不兼容项。
测试脚本如下:
TENANT_ID='common' CLIENT_ID='475c75f3-9fdc-4d23-8956-104342a43740' output=$( curl -s https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/devicecode \ -X POST \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d "client_id=${CLIENT_ID}&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default" ) echo "URL: $(jq -r '.verification_uri' <<<$output)" echo "CODE: $(jq -r '.user_code' <<<$output)" read curl -s https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token \ -X POST \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d "grant_type=urn:ietf:params:oauth:grant-type:device_code&client_id=${CLIENT_ID}&device_code=$(jq -r '.device_code' <<<$output)"
脚本返回错误如下:
{ "error": "invalid_scope", "error_description": "AADSTS70011: The provided value for the input parameter 'scope' is not valid. One or more scopes in 'https://graph.microsoft.com/.default' are not compatible with each other.\r\nTrace ID: 9d5809b7-32ad-4c18-a8d8-4ac49a439100\r\nCorrelation ID: eb10447d-fce6-4a33-b669-c62924f4e08a\r\nTimestamp: 2022-06-12 09:59:54Z", "error_codes": [ 70011 ], "timestamp": "2022-06-12 09:59:54Z", "trace_id": "9d5809b7-32ad-4c18-a8d8-4ac49a439100", "correlation_id": "eb10447d-fce6-4a33-b669-c62924f4e08a" }
核心疑问:为何使用.default scope时触发兼容性错误,指定具体权限scope可正常执行?
故障原因与解决方案
根本原因
.default scope的设计逻辑是请求应用注册环节预先配置好的所有权限,它本身不能和Microsoft Graph的动态权限(比如User.Read、openid、profile、offline_access这类OpenID Connect基础scope)混合使用。
触发这次报错的核心原因有两个:
- 你用
common作为租户标识发起请求时,AAD会自动给公共客户端追加openid、profile、offline_access三个OIDC基础scope,这三个属于动态权限范畴,和.default的静态权限请求逻辑互斥。 - 你代码里用的客户端ID
475c75f3-9fdc-4d23-8956-104342a43740是微软官方的通用测试客户端,这个客户端没有在应用注册里预先配置静态的Graph权限列表,用.default发请求时解析不出合法的权限集合,就会抛出scope不兼容的错误。
解决方案
根据使用场景二选一即可:
- 如果只是测试Graph接口调用:不要使用
.defaultscope,直接指定你需要的具体动态权限即可,比如["https://graph.microsoft.com/User.Read"],MSAL会自动追加必要的OIDC基础scope,设备码流可以正常执行。 - 如果必须使用
.defaultscope:- 不要使用
common租户,替换为你自己的Azure AD租户ID - 不要使用微软公开的测试客户端ID,改用你自己在Azure AD中注册的应用客户端ID
- 提前在你自己的应用注册的「API权限」页面,配置好所有需要的Microsoft Graph权限,完成管理员授权后,再用
.defaultscope请求令牌即可。
- 不要使用
注意:
.defaultscope仅适用于自有应用注册的静态权限场景,公共客户端+通用租户+第三方资源的场景下,直接声明具体需要的权限才是符合AAD v2.0端点规范的用法。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

