User.HasClaim не может успешно прочитать свойства заявки в .NET Core 2.0 Web Api - PullRequest
0 голосов
/ 24 апреля 2018

У меня проблема при использовании атрибута Authorize с политикой, которую я определяю в Startup.cs. Я отредактировал свой контроллер, чтобы вручную проверить претензии. Я вижу претензии, включая претензию по объему, с правильными областями, но когда я вручную проверяю эту претензию / область, она возвращается как ложная. Я использую Azure AD B2C в качестве сервера идентификации и успешно получаю проверенный токен.

Вот код из моего Startup.cs:

    services.AddAuthorization(options =>
    {
        var policyRead = new AuthorizationPolicyBuilder()
            .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
            .RequireAuthenticatedUser()
            .RequireClaim("http://schemas.microsoft.com/identity/claims/scope", "vendor.read")
            .Build();
        options.AddPolicy("VendorRead", policyRead);

        var policyWrite = new AuthorizationPolicyBuilder()
            .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
            .RequireAuthenticatedUser()
            .RequireClaim("http://schemas.microsoft.com/identity/claims/scope", "vendor.write")
            .Build();
        options.AddPolicy("VendorWrite", policyWrite);
    });

    services.AddAuthentication(sharedOptions =>
    {
        sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    }) 
        .AddJwtBearer(jwtOptions =>
        {
            jwtOptions.Authority = $"{Configuration["AzureAdB2C:Instance"]}/{Configuration["AzureAdB2C:TenantId"]}/{Configuration["AzureAdB2C:SignUpSignInPolicyId"]}/v2.0/";
            jwtOptions.Audience = Configuration["AzureAdB2C:ClientId"];
            jwtOptions.RequireHttpsMetadata = true;
            jwtOptions.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = $"{Configuration["AzureAdB2C:Instance"]}/{Configuration["AzureAdB2C:TenantId"]}/v2.0/",
                ValidAudience = Configuration["AzureAdB2C:ClientId"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["AzureAdB2C:ClientSecret"]))
            };
            jwtOptions.Events = new JwtBearerEvents
            {
                OnAuthenticationFailed = AuthenticationFailed,
                OnTokenValidated = TokenValidated
            };
        });

Вот код моего контроллера, где я вручную проверяю заявки:

// GET: api/Vendor/5
[HttpGet("{id}")]
public async Task<IActionResult> Get(VendorRequest request)
{
    var hasClaim1 = User.HasClaim(c => c.Type == "vendor.read");
    var hasClaim2 = User.HasClaim(c => c.Type == "scope");
    var hasClaim3 = User.HasClaim(c => c.Type == "scp");
    var hasClaim4 = User.HasClaim(c => c.Type == "http://schemas.microsoft.com/identity/claims/scope");
    var hasClaim5 = User.HasClaim("http://schemas.microsoft.com/identity/claims/scope", "vendor.read");
    var hasClaim7= User.HasClaim("http://schemas.microsoft.com/identity/claims/scope", "vendor.write");
    var allowed = await _authorization.AuthorizeAsync(User, "VendorRead");
    if (!allowed.Succeeded)
    {
        return StatusCode(StatusCodes.Status403Forbidden);
    }

Единственным hasClaim, который возвращается как истинный, является hasClaim4.

Вот как выглядят мои претензии: enter image description here

Есть идеи, что я делаю не так? Я только сейчас пытаюсь заставить работать сферу vendor.read.

Ответы [ 3 ]

0 голосов
/ 25 апреля 2018

Это то, что я должен был сделать, чтобы заставить его работать с атрибутом [Authorize ("VendorRead")]:

private Task TokenValidated(TokenValidatedContext arg)
{
    var identity = arg.Principal.Identity as ClaimsIdentity;
    var scopeClaims = identity?.Claims.FirstOrDefault(c => c.Type.Contains("scope"))?.Value.Split(' ').ToList();

    if (scopeClaims != null)
    { 
        foreach (var scope in scopeClaims)
        {
            identity?.AddClaim(new Claim("scope", scope));
        }
    }

    return Task.FromResult(0);
}

Я добавил этот метод в Startup.cs, который вызывается, когдатокен проверенВы можете увидеть это выше, когда я определю JwtBearerEvents.

0 голосов
/ 17 мая 2018

Заявка на область действия является списком с пробелами, поэтому помощник RequireClaim() не будет работать в этом случае, но более общий RequireAssertion() будет работать.

Пример объема заявки

"scp": "demo.read demo.write user_impersonation Test-Value"

Образец RequireAssertion()

services.AddAuthorization(options =>
{
    options.AddPolicy("ScopeCheck", policyBuilder => 
     policyBuilder
     .RequireAssertion(async handler =>
       {
           var scopeClaim = handler.User.FindFirst("http://schemas.microsoft.com/identity/claims/scope");
           var scopes = scopeClaim?.Value.Split(' ');
           var hasScope = scopes?.Where(scope => scope == "demo.write").Any() ?? false;
           return hasScope;
       }));
});

Образец Controller

[Authorize("ScopeCheck")]
public class SecureController : Controller
{
    [HttpGet]
    public IActionResult Test()
    {
        return Ok(new { Message = "You are allowed" });
    }
}

Полный образец проекта - Образец токена


Область доступа токена (RFC 6749 section-3.3)

Значение параметра scope выражается в виде списка строк, разделенных пробелами, с учетом регистра.Строки определяются сервером авторизации.Если значение содержит несколько строк, разделенных пробелом, их порядок не имеет значения, и каждая строка добавляет дополнительный диапазон доступа к запрошенной области действия

0 голосов
/ 24 апреля 2018

Судя по вашему коду, vendor.read на самом деле является требованием значение , а не типом.

Кроме того, FWIW, весь смысл настройки политик заключается вне нужно делать этот тип проверки вручную.Просто украсьте свое действие:

[Authorize(Policy = "VendorRead")]
...