Azure AD — Использование маркера доступа к API Graph из Angular SPA в веб-API C#

#c# #asp.net-core #microsoft-graph-api #msal #msal-angular

Вопрос:

Похоже, мне не хватает чего-то фундаментального, когда речь заходит о корпоративных приложениях Azure AD.
У меня есть приложение, работающее как Angular SPA с внутренним API AspNetCore, которое имеет 2 отдельные регистрации приложений в Azure AD. MyAPI отображается как область «access_as_user» в MySPA.
MyAPI не имеет собственного потока аутентификации.

Я хочу реализовать вызовы API MS Graph с делегированным доступом через MyAPI. В настоящее время он работает только как демоническая служба с разрешениями приложения.

MySPA может позвонить https://graph.microsoft.com/v1.0/me/ без каких-либо проблем и профиль возвращается.
Я вижу, что у jwt есть пользователь.Область чтения:

 "scp": "openid profile User.Read email"
 

MyAPI не выполняет тот же запрос со следующей ошибкой:

 code: "InvalidAuthenticationToken"
message: "Access token validation failure. Invalid audience."
 
 public async Task<IActionResult> GetProfile([FromHeader] string authorization)
{
   var tokenFromHeader = authorization.Replace("Bearer ", "");
   return await ("https://graph.microsoft.com/v1.0/me/")
      .WithOAuthBearerToken(tokenFromHeader)
      .WithHeader("Content-Type", "application/json")
      .GetJsonAsync();
    }
 

У JWT, естественно, есть разрешение с областью действия, поэтому ошибка аудитории имеет смысл

 "aud": "api://XXXXXXXXXXXXXXXXXXXXXXXX",
"scp": "access_as_user"
 

Как MyAPI может получить доступ к API MS Graph от имени пользователей ?

Ответ №1:

Удалось решить эту проблему с помощью Graph SDK

Я добавил следующее в свой запуск после .AddMicrosoftIdentityWebApi(Configuration)

 .EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph()
.AddInMemoryTokenCaches();
 

Это позволило мне внедрить клиент службы в мой контроллер API:

 public GraphAPIController(GraphServiceClient client)
{
   this.client = client;
}

public async Task<IActionResult> GetProfile()
{
   return await client.Me.Request().GetAsync();
}