MicrosoftIdentityWebApiAuthentication - 无效的令牌签名

MicrosoftIdentityWebApiAuthentication - Invalid Token Signature

我的 SharePoint Add-in 运行此 JavaScript 以从我的问候 API:

中获取消息
async function getGreeting() {
    // https://www.youtube.com/watch?v=P3vkerr1nW8
    var client = new Msal.UserAgentApplication(config);
    var request = {
        scopes: ['user.read'],
        prompt: 'select_account'
    };
    let loginResponse = await client.loginPopup(request);
    let tokenResponse = await client.acquireTokenSilent(request);
    var theToken = tokenResponse.accessToken;
    // https://zinoui.com/blog/jquery-ajax-headers
    $.ajax({
        url: 'https://localhost:44316/Greeting',
        type: 'GET',
        headers: {
            'Authorization': 'Bearer ' + theToken
        },
        timeout: 600000,
        success: function (theGreeting) { alert(theGreeting); },
        error: function () { alert('Error'); }
    });
}

我的 ASP.NET Core 3.1 控制器有这个代码:

namespace SharePointTestAPI.Controllers
{
    // https://www.yogihosting.com/aspnet-core-enable-cors/
    [Authorize]
    [EnableCors("SharePointOnline")]
    [ApiController]
    [Route("[controller]")]
    public class GreetingController : ControllerBase
    {
        [HttpGet]
        public String Get()
        {
            return "Great Value Canned Salmon is Rich in Omega-3 and Vitamin D!!!";
        }
    }
}

如果我注释掉 [Authorize] 属性,将弹出一个警告框并显示有关 Walmart Salmon 的预期消息。不幸的是,如果我放回 [Authorize] 属性,我会在响应 header:

中看到此错误

WWW-Authenticate: Bearer error="invalid_token", error_description="The signature is invalid"

我从 acquireTokenSilent 取回的令牌在客户端和服务器上看起来都不错。在这两种情况下,它们在 https://jwt.ms/ 处都可以很好地解码,所以我不知道为什么 MicrosoftIdentityWebApiAuthentication 似乎在抱怨令牌无效。

我在 Startup.cs 中的 ConfigureServices 函数如下所示:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
        {
            // https://docs.microsoft.com/en-us/aspnet/core/security/cors?view=aspnetcore-5.0
            // https://www.yogihosting.com/aspnet-core-enable-cors/
            options.AddPolicy(
                "SharePointOnline",
                builder =>
                {
                    builder.WithOrigins(
                        "https://myTestTenant-3b3547c0f805ae.sharepoint.com"
                    ).AllowAnyHeader().AllowAnyMethod();
                }
            );
        }
    );


    services.AddMicrosoftIdentityWebApiAuthentication(Configuration, "AzureAd");

    services.AddControllers();
}

这是我经过消毒的 appsettings.json:

{
/*
The following identity settings need to be configured
before the project can be successfully executed.
For more info see https://aka.ms/dotnet-template-ms-identity-platform 
*/
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "myTenantName.onmicrosoft.com",
    "TenantId": "[someGUID]",
    "ClientId": "api://[someOtherGUID]",

    "CallbackPath": "/signin-oidc"
  },

  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

谁能帮我理解为什么 MicrosoftIdentityWebApiAuthentication 似乎认为我的身份验证令牌已损坏?

我一直收到“无效的令牌签名”错误,因为我错误地取回了访问令牌而不是 ID 令牌...我需要更改我的 getGreeting 函数中的以下行:

var theToken = tokenResponse.accessToken;

var theToken = tokenResponse.idToken.rawIdToken;

修复此问题后,我不断收到与签名错误无关的“无效受众”错误。为了摆脱它,我 认为 我必须通过“公开 API”部分在 Azure AD 中创建一个 appRoles 范围:

创建该 appRoles 范围后,我还更改了 getGreeting 函数中的范围请求:

scopes: ['user.read'],

scopes: ['api://[myClientId]/appRoles'],

认为 这些额外的更改允许我的 SharePoint 加载项从 my API 而不是 Microsoft 获取令牌图形。完成上述两项更改后,我的 API 向我的 SharePoint 加载项返回了预期的问候语。

我的新getGreeting函数如下所示:

async function getGreeting() {
    // https://www.youtube.com/watch?v=P3vkerr1nW8
    var client = new Msal.UserAgentApplication(config);
    var request = {
        scopes: ['api://[myClientId]/appRoles'],
        prompt: 'select_account'
    };
    let loginResponse = await client.loginPopup(request);
    let tokenResponse = await client.acquireTokenSilent(request);
    var theToken = tokenResponse.idToken.rawIdToken; 
    // https://zinoui.com/blog/jquery-ajax-headers
    $.ajax({
        url: 'https://localhost:44316/Greeting',
        type: 'GET',
        headers: {
            'Authorization': 'Bearer ' + theToken
        },
        timeout: 600000,
        success: function (theGreeting) { alert(theGreeting); },
        error: function () { alert('Error'); }
    });
}  

最后,我在 Web API 的 appsettings.json 文件中将我的 ClientId 更改为:

"ClientId": "api://[someOtherGUID]",

返回(不带前导 api://):

"ClientId": "[someOtherGUID]",

我的最终 appsettings.json 显示在这里:

{
/*
The following identity settings need to be configured
before the project can be successfully executed.
For more info see https://aka.ms/dotnet-template-ms-identity-platform 
*/
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "myTenantName.onmicrosoft.com",
    "TenantId": "[someGUID]",
    "ClientId": "[someOtherGUID]",

    "CallbackPath": "/signin-oidc"
  },

  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}