我正在努力了解基于角色的授权在 Azure 应用程序服务中是如何工作的。 它适用于用户,但不适用于服务主体(应用程序注册)。 我的设置:
在我的代码中,我有以下设置:
Microsoft.Indeitity.Web
(2.17版本,目前最新)// Makes the roles come in 'role' claim
System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
builder.Services.AddMicrosoftIdentityWebAppAuthentication(builder.Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
builder.Services.AddAuthorization();
builder.Services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
{
// Sets up the claim name which will be used by Authorize attribute
options.TokenValidationParameters.RoleClaimType = "roles";
});
[ApiController]
[Route("[controller]")]
public class Test : ControllerBase
{
[HttpGet("Reader")]
[Authorize(Roles = "Reader")]
public IActionResult Reader() =>
Ok("Success")
}
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "{mytenant}.onmicrosoft.com",
"TenantId": "{tenantid}",
"ClientId": "{AR client id}",
"ClientSecret": "{AR client secret}",
"Scopes": "access_as_user",
"CallbackPath": "/signin-oidc"
},
现在,当我将此应用程序部署到应用程序服务时,对于用户访问 Reader 控制器正在按预期工作。
我还创建了索赔控制器:
[HttpGet("GetClaims")]
public IActionResult GetClaims()
{
var sb = new System.Text.StringBuilder("Claims:\r\n\r\n");
User.Claims.ToList().ForEach(_ => sb.AppendLine($"Key: '{_.Type}'\tValue: '{_.Value}'"));
sb.AppendLine();
sb.AppendLine("\r\n\r\nHeaders:\r\n\r\n");
ClaimsPrincipal.Current?.Claims.ToList().ForEach(_ => sb.AppendLine($"Type: '{_.Type}'\tSubject: '{_.Subject}'\tIssuer: '{_.Issuer}'\tValueType: '{_.ValueType}'\tValue: '{_.Value}'"));
return Ok(sb.ToString());
}
但是当我尝试使用服务主体(例如通过逻辑应用程序)访问它时,它给了我空声明,这意味着在访问
Reader
控制器时授权也不起作用:
我相信我在这里遗漏了一些小东西,很难相信微软没有实现基于角色的服务主体授权。
作为其他解决方法,我相信我会创建一个中间件来映射服务主体令牌中的声明,但如果可能的话,我真的想避免这种情况。
好吧,我终于成功地使基于角色的授权对用户和服务主体都有效,例如 AR 或 MI。 我需要更改的只是 Program.cs,如下所示:
// Makes the roles come in 'role' claim
System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
// Set up for OpenId / user based authentication
builder.Services
.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration)
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
// Set up for service principal based authentication
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration);
builder.Services.AddAuthorization();
// Sets up the claim name which will be used by Authorize attribute for open id / user
builder.Services.Configure<OpenIdConnectOptions>(OpenIdConnectDefaults.AuthenticationScheme, options =>
options.TokenValidationParameters.RoleClaimType = "roles"
);
builder.Services.Configure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
options.TokenValidationParameters.RoleClaimType = "roles"
);