MicrosoftIdentityWebApiAuthentication - недействительная подпись токена

Моя надстройка SharePoint запускает этот JavaScript, чтобы получить сообщение от моего Greeting 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!!!";
        }
    }
}

Если я закомментирую атрибут [Авторизовать], появится окно с предупреждением, в котором будет показано ожидаемое сообщение о Walmart Salmon. К сожалению, если я верну атрибут [Authorize], я увижу эту ошибку в заголовке ответа:

WWW-Authenticate: Bearer error = invalid_token, error_description = Подпись недействительна

Токены, которые я получаю от acquTokenSilent, хорошо смотрятся как на клиенте, так и на сервере. В обоих случаях они отлично декодируют на https://jwt.ms/, поэтому я не знаю, почему MicrosoftIdentityWebApiAuthentication похоже, жалуется, что токены недействительны.

Моя функция ConfigureServices в Startup.cs выглядит так:

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, похоже, думает, что мой токен аутентификации поврежден?


person Shawn Eary    schedule 24.03.2021    source источник


Ответы (1)


Я продолжал получать ошибку недопустимой подписи токена, потому что я ошибочно возвращал токен доступа вместо токена Id ... Мне нужно было изменить следующую строку в моей функции getGreeting с:

var theToken = tokenResponse.accessToken;

to

var theToken = tokenResponse.idToken.rawIdToken;

После того, как это было исправлено, я продолжал получать ошибки недействительной аудитории, которые не были связаны с ошибкой подписи. Чтобы избавиться от этого, я думаю, что мне пришлось создать область appRoles в Azure AD через раздел Expose an API:

введите описание изображения здесь

После создания области appRoles я также изменил запрос областей в моей функции getGreeting с:

scopes: ['user.read'],

to

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

Я думаю, что эти дополнительные изменения позволили моей надстройке SharePoint получить токен от моего API вместо Microsoft Graph. Как только я внес два вышеуказанных изменения, мой 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'); }
    });
}  

Наконец, я изменил свой ClientId в файле appsettings.json своего веб-API с:

"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": "*"
}
person Shawn Eary    schedule 31.03.2021