#c# #asp.net-web-api #azure-ad-b2c #msal
#c# #asp.net-web-api #azure-ad-b2c #msal
Вопрос:
У меня есть две службы веб-API (исходная и целевая). Все они зарегистрированы в Azure B2C как приложения AD с использованием клиентских секретов.
Я пытаюсь вызвать вызов gRPC API из исходной службы в API целевой службы, однако, когда я пытаюсь выполнить вызов, я получаю исключение gRPC, в котором говорится, что источник не прошел проверку подлинности.
Примечание: Когда я удаляю политику области действия и авторизованные атрибуты из целевого WebAPI, все работает нормально, но, конечно, это небезопасно.
При запуске исходной службы у меня есть следующее…
Примечание: настройки конфигурации верны как для источника, так и для цели. Я трижды проверил правильность всех настроек конфигурации.
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddMicrosoftIdentityWebApi(options =>
{
Configuration.Bind("AzureAdB2C", options);
options.TokenValidationParameters.NameClaimType = "name";
},
options =>
{
Configuration.Bind("AzureAdB2C", options);
});
Я не уверен, требуется ли это, но я также включил следующую логику в запуск исходного API.
Примечание: на данный момент я жестко запрограммировал требуемые области.
services.AddMicrosoftIdentityWebAppAuthentication(Configuration, "AzureAdB2C")
.EnableTokenAcquisitionToCallDownstreamApi(new string[] { "https://nextwaredev.onmicrosoft.com/nextware.productportal.sharedservices.api/sharedservices_readaccess", "https://nextwaredev.onmicrosoft.com/nextware.productportal.sharedservices.api/sharedservices_readwriteaccess" })
.AddInMemoryTokenCaches();
Целевая служба имеет правильные политики, и обе службы настроены на использование авторизации и аутентификации..
app.UseAuthentication();
app.UseAuthorization();
Я добавил разрешения API, которые требуются для источника, на основе тех же областей, указанных выше..
Когда я пытаюсь вызвать метод в целевом API, я получаю обратно исключение gRPC, в котором говорится, что источник не прошел проверку подлинности.
Итак, я подумал, что, возможно, мне нужно передать токен доступа к приложению, однако, когда я пытаюсь получить токен доступа JWT (следуя этому примеру, вызывающему tokenAcquisition.GetAccessTokenForAppAsync) Я получаю другое исключение «AADB2C90086: предоставленный grant_type [client_credentials] не поддерживается».
Примечание: у меня есть приложение Blazor, у которого нет проблем с вызовом тех же защищенных API. Однако там я вызываю GetAccessTokenForUserAsync… который возвращает правильный токен с примененными областями, необходимыми для вызова тех же исходных или целевых служб веб-api.
Должен ли я включать AddMicrosoftIdentityWebAppAuthentication при запуске? Что еще я делаю не так?
Спасибо за вашу помощь! Приветствия
Комментарии:
1. Не могли бы вы рассказать мне, как вы вызываете целевой API
Ответ №1:
Я не смог заставить поток учетных данных клиента работать с использованием Microsoft Identity Web Api непосредственно из Azure B2C, поэтому вместо этого я последовал этому превосходному руководству @Hossam Barakat по этой ссылке
Я закончил с двумя типами аутентификации, один из которых позволяет осуществлять связь с Web API => Web API с использованием Jwt Bearer, а другой используется Web APP => Web API, который использует
- Элемент списка
Веб-api Microsoft Identity …
var authority = @"https://login.microsoftonline.com/" Configuration["AzureAdB2C:TenantId"];
var validIssuer = @"https://login.microsoftonline.com/" Configuration["AzureAdB2C:TenantId"] @"/v2.0";
var audience = Configuration["AzureAdB2C:ClientId"];
var validAudience = Configuration["AzureAdB2C:ClientId"];
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer("APIToAPI", options =>
{
options.Audience = audience;
options.Authority = authority;
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidAudience = validAudience,
ValidIssuer = validIssuer
};
}
)
.AddMicrosoftIdentityWebApi(options =>
{
Configuration.Bind("AzureAdB2C", options);
options.TokenValidationParameters.NameClaimType = "name";
}
, options =>
{
Configuration.Bind("AzureAdB2C", options);
},
jwtBearerScheme: "AppToAPI"
);
Затем, чтобы включить обе схемы, мне пришлось добавить следующее…
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().AddAuthenticationSchemes("APIToAPI", "APPToAPI").Build();
}
Я также добавил следующий атрибут авторизации к действиям контроллера…
[Authorize(AuthenticationSchemes = "APIToAPI, APPToAPI")]
Создание токена для каждого типа отличается.
Это то, что я использую для получения токена доступа для текущего пользователя, прошедшего проверку подлинности, в веб-приложении, вызывая API…
private static string GetAccessTokenForUser(List<string> scopes)
{
if (scopes != null)
{
var container = ContainerLocator.Current.Container;
var configuration = container.Resolve<IConfiguration>();
var httpContextAccessor = container.Resolve<IHttpContextAccessor>();
if (httpContextAccessor?.HttpContext?.User?.Identity?.IsAuthenticated ?? false)
{
var tokenService = httpContextAccessor.HttpContext.RequestServices.GetRequiredService<ITokenAcquisition>();
try
{
return Task.Run(() => tokenService.GetAccessTokenForUserAsync(scopes)).Resu<
}
catch (System.Exception ex)
{
Log.Error(ex, "error while loading token for current user, try to login again");
}
}
}
return null;
}
Это то, что я использую для получения токена доступа, когда это веб-API, вызывающий веб-API…
public static async Task<TokenResponse> GetAccessTokenAsync(string scope)
{
var client = new HttpClient();
var container = ContainerLocator.Current.Container;
var configuration = container.Resolve<IConfiguration>();
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = @"https://login.microsoftonline.com/" configuration["AzureAdB2C:Domain"] @"/oauth2/v2.0/token",
ClientId = configuration["AzureAdB2C:ClientId"],
ClientSecret = configuration["AzureAdB2C:ClientSecret"],
Scope = scope
});
if (tokenResponse.IsError)
{
return null;
}
return tokenResponse;
}
Если токен доступа получен, он просто добавляется в заголовок запроса перед вызовом метода gRPC и / или REST API.
Я надеюсь, что это поможет другим.
Комментарии:
1. Привет. Вы нашли способ вернуть утверждения в токене доступа?
2. У вас есть репо для этого?