Azure AD Bearer Token 有错误的 "aud" 声明

Azure AD Bearer Token has wrong "aud" claims

我正在尝试对 Visio VSTO 插件使用 AAD 委派权限不记名令牌,以使用 CSOM 创建 SharePoint Online 页面。最初我能够在 Modern Authentication with CSOM for Net Standard

之后输入用户名/密码来完成这项工作

但是,我希望用户 select 现有 AAD 帐户。当我尝试使用以下代码时,Bearer 令牌“aud”声明始终设置为“00000003-0000-0000-c000-000000000000”,即图表 API。返回 ClientContext 对象时,我在执行页面查找时收到 HTTP 401 Unauthorized 错误。

代码如下

            //
            // Get Client App
            //
            var ClientApp = (PublicClientApplication)PublicClientApplicationBuilder.Create(<AAD App ID>)
           .WithDefaultRedirectUri()
           .WithTenantId(<AAD Tenant ID>)
           .WithAuthority(AzureCloudInstance.AzurePublic, <AAD Tenant ID>)
           .Build();
            
            //
            // Prompt for user to select preferred AAD account
            // The returned JWT Bearer Token "aud" claim is 00000003-0000-0000-c000-000000000000
            //
            var Token = ClientApp.AcquireTokenInteractive(scopes)
              .WithPrompt(Prompt.SelectAccount)
              .WithParentActivityOrWindow(GetActiveWindow())
              .ExecuteAsync()
              .GetAwaiter()
              .GetResult();

            //
            // Get client Context
            //
            var ClientContext = AuthenticationManager.GetAzureADAccessTokenAuthenticatedContext(<SharePoint Site URL>, Token.AccessToken);

            //
            // Using the Client Context to query the Site results in HTTP 401
            //
           ClientContext.Load(ClientContext.Web, p => p.Title, t => t.Description);
           ClientContext.ExecuteQuery();

查看上面 link 中 AuthenticationManager class 的代码,我可以看到 AAD Bearer 请求正在将以下资源请求参数传递给 SharePoint online URL:

var body = $"resource={resource}&client_id={clientId}&grant_type=password&username={HttpUtility.UrlEncode(username)}&password={HttpUtility.UrlEncode(password)}";

看来 AAD 正在根据此参数设置 Bearer 令牌“aud”声明。但是,当我尝试使用 'WithExtraQueryParameters' 添加此参数时,出现以下错误:“AADSTS901002:不支持 'resource' 请求参数”

好的,我找到问题了。范围需要以资源为前缀:

string[] scopes = { "https://<domain>.sharepoint.com/AllSites.Write", "user.read" }

然后取回令牌

 this.Token = await ClientApp.AcquireTokenInteractive(scopes)
                                                .WithPrompt(Prompt.SelectAccount)
                                                .WithParentActivityOrWindow(GetActiveWindow())
                                                .ExecuteAsync();