Мне сложно понять, как повторно использовать маркер безопасности пользователя, чтобы аутентифицировать его, когда его запрос данных проходит через несколько веб-API.
Console App
- C # / Net Framework 4.7.x консольное приложение.
WebAPI 1
- Приложение C # / .Net Core 2.2 MVC WebAPI.
WebAPI 2
- Приложение C # / .Net Core 2.2 MVC WebAPI.
В настоящее время все они настроены как автономные приложения в своих собственных решениях Visual Studio 2019, работающих на моем компьютере разработчика, но (когда они будут работать !!) каждый из них будет размещаться в Azure как отдельный объект самостоятельно.
По сути, пользователь проходит проверку подлинности в Консольном приложении, проверяя свои учетные данные из Azure Active Directory. После этого образца на GitHub у меня есть консольное приложение, которое успешно вызывает WebAPI 1
и возвращает данные.
Однако я хочу, чтобы WebAPI 1
звонил WebAPI 2
во время вызова и извлекал другие данные как часть набора данных для Консольного приложения, и это та часть, с которой я застрял.
WebAPI 2
настроен на портале Azure точно так же, как и WebAPI 1
, за исключением различных идентификаторов клиентов приложений и т. Д.
Как часть примера (упомянутого выше), я могу WebAPI 1
вызвать Microsoft Graph API перед возвратом данных обратно на вызывающий Console App
, так что я не думаю, что я способ от этого. Вот код для вызова Graph API:
public async Task<string> CallGraphApiOnBehalfOfUser()
{
string[] scopes = { "user.read" };
// we use MSAL.NET to get a token to call the API On Behalf Of the current user
try
{
string accessToken = await _tokenAcquisition.GetAccessTokenOnBehalfOfUser(HttpContext, scopes);
dynamic me = await CallGraphApiOnBehalfOfUser(accessToken);
return me.userPrincipalName;
}
catch (MsalUiRequiredException ex)
{
_tokenAcquisition.ReplyForbiddenWithWwwAuthenticateHeader(HttpContext, scopes, ex);
return string.Empty;
}
}
private static async Task<dynamic> CallGraphApiOnBehalfOfUserOriginal(string accessToken)
{
//
// Call the Graph API and retrieve the user's profile.
//
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
HttpResponseMessage response = await client.GetAsync("https://graph.microsoft.com/v1.0/me");
string content = await response.Content.ReadAsStringAsync();
if (response.StatusCode == HttpStatusCode.OK)
{
dynamic me = JsonConvert.DeserializeObject(content);
return me;
}
throw new Exception(content);
}
Мой план состоял в том, чтобы изменить URL-адрес в приведенном выше коде, чтобы он указывал на адрес WebAPI 2
, но во время аутентификации он не удался ЕСЛИ я удаляю атрибут класса [Authorize] на моем контроллере в WebAPI 2
, он успешно устанавливает соединение и возвращает ожидаемые данные, но с включенным атрибутом он даже не достигает точки останова на Контроллер, подсказывая мне, что проблема в маркере носителя, который я пытаюсь использовать ИЛИ , что WebAPI 2 не настроен должным образом.
Получение копии токена безопасности и попытка повторно использовать этот промежуточный полет также не работает, так как я предполагаю, что токен предназначен для WebAPI 1
и поэтому недопустим для использования с WebAPI 2
.
Должен ли я выполнять такую аутентификацию на стороне? (Кажется грязным, когда пользователь жестко кодирует учетные данные в WebAPI 1
, которые могут получить доступ к WebAPI 2
, поэтому я не хочу этого делать. Плюс, если учетные данные пользователя требуют изменения, у меня есть перераспределение только для что.)
Есть ли лучший способ сделать то, что я пытаюсь сделать?
Если вам понадобится дополнительная информация, чтобы объяснить, что я сделал, я, безусловно, могу это сделать.
ОБНОВЛЕНИЕ 1: Вот Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddProtectWebApiWithMicrosoftIdentityPlatformV2(Configuration)
.AddProtectedApiCallsWebApis(Configuration, new string[] { "user.read", "offline_access" })
.AddInMemoryTokenCaches();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseMvc();
}
ОБНОВЛЕНИЕ 2: Аналогичное сообщение переполнения стека
С тех пор я нашел этот пост , который @ philippe-signoret описывает в своем ответе, и это именно то, что мне нужно.
ОБНОВЛЕНИЕ 3: несанкционированный ответ при вызове WebAPI 2
Вот сообщение об ошибке, которое я получаю после звонка:
{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content: System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers:
{
Server: Kestrel
WWW-Authenticate: Bearer error="invalid_token", error_description="The signature is invalid"
X-SourceFiles: =?UTF-8?B?*<random-looking-code>*
X-Powered-By: ASP.NET
Date: Fri, 31 May 2019 09:48:31 GMT
Content-Length: 0
}}
Как я упоминал ранее, если я удалю атрибут [Authorize] из класса моего контроллера, вызов пройдет, как и ожидалось.