Joh*_*ars 0 c# asp.net-web-api azure-ad-b2c azure-ad-msal
我有两个 Web API 服务(源和目标)。每个都使用客户端密钥在 Azure B2C 中注册为 AD 应用程序。
我正在尝试调用从源服务到目标服务 API 的 gRPC API 调用,但是当我尝试进行调用时,出现 gRPC 异常,表明源未经身份验证。
注意:当我从目标 WebAPI 中删除范围策略和授权属性时,一切正常,但当然这是不安全的。
在源服务启动中我有以下内容......
注意:源和目标的配置设置都是正确的。我已经三次检查所有配置设置是否正确。
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddMicrosoftIdentityWebApi(options =>
{
Configuration.Bind("AzureAdB2C", options);
options.TokenValidationParameters.NameClaimType = "name";
},
options =>
{
Configuration.Bind("AzureAdB2C", options);
});
Run Code Online (Sandbox Code Playgroud)
我不确定是否需要,但我还在源 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();
Run Code Online (Sandbox Code Playgroud)
目标服务具有正确的策略,并且两个服务都配置为使用授权和身份验证。
app.UseAuthentication();
app.UseAuthorization();
Run Code Online (Sandbox Code Playgroud)
我已经根据上面的相同范围添加了源所需的 API 权限。
当我尝试调用目标 API 上的方法时,我收到一个 gRPC 异常,表明源未经身份验证。
因此,我想也许我需要传递应用程序访问令牌,但是当我尝试获取 JWT 访问令牌时(以下示例 调用 tokenAcquisition.GetAccessTokenForAppAsync),我收到另一个异常“AADB2C90086:不支持提供的 grant_type [client_credentials]。 ”
注意:我有一个 Blazor 应用程序,调用相同的安全 API 时没有任何问题。不过,我调用 GetAccessTokenForUserAsync... ,它返回正确的令牌,并具有调用相同下游源或目标 Web api 服务所需的应用范围。
我是否需要在启动时包含 AddMicrosoftIdentityWebAppAuthentication?我还做错了什么?
谢谢您的帮助!干杯
我无法直接从 Azure B2C 使用Microsoft Identity Web Api获取客户端凭据流,因此我按照此链接遵循了 @Hossam Barakat 的出色指导
我以两种身份验证类型结束,一种允许使用Jwt Bearer进行 Web API => Web API 通信,另一种由 Web APP 使用 => 利用 Jwt Bearer 的 Web API
微软身份网络 API ...
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"
);
Run Code Online (Sandbox Code Playgroud)
然后为了启用这两个方案,我必须添加以下内容......
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().AddAuthenticationSchemes("APIToAPI", "APPToAPI").Build();
}
Run Code Online (Sandbox Code Playgroud)
我还在控制器操作中添加了以下授权属性...
[Authorize(AuthenticationSchemes = "APIToAPI, APPToAPI")]
Run Code Online (Sandbox Code Playgroud)
每种类型的令牌创建都是不同的。
这就是我用来获取 Web 应用程序中当前经过身份验证的用户的访问令牌、调用 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)).Result;
}
catch (System.Exception ex)
{
Log.Error(ex, "error while loading token for current user, try to login again");
}
}
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
当 Web API 调用 Web 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;
}
Run Code Online (Sandbox Code Playgroud)
如果获取了访问令牌,则只需在调用 gRPC 和/或 REST API 方法之前将其添加到请求标头中即可。
我希望这对其他人有帮助。
| 归档时间: |
|
| 查看次数: |
1355 次 |
| 最近记录: |