Web Api 2: авторизация по пользовательским утверждениям

В некоторых контроллерах я хочу авторизовать пользователя по идентификатору компании.

Например, рассмотрим следующий ресурс:

api/v1/companies/1234/orders

Это должно быть доступно только пользователям, принадлежащим к компании 1234.

Обратите внимание, что я использую аутентификацию носителя токена OAuth.

Создание претензии компании в OAuthAuthorizationServerProvider:

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    //...

    var identity = new ClaimsIdentity(context.Options.AuthenticationType);

    // Creating the companyId claim
    identity.AddClaim(new Claim("CompanyId", user.CompanyId.ToString()));

    context.Validated(identity);
}

Текущая реализация controller для ресурса заказов:

[RoutePrefix("api/v1/companies/{companyId:Guid}/orders")]
public class OrdersController : ApiController
{
    [Route]
    public IHttpActionResult GetOrders(Guid companyId)
    {
        var orders = OrdersRepository.Get(companyId);

        return Ok(orders.Select(x => OrderModel.From(x)));
    }
}

Где я могу авторизовать значение URL-адреса companyId для утверждения личности?

Можно ли здесь как-то использовать [Authorize]?


person Dave New    schedule 26.01.2015    source источник
comment
Почему вы не можете использовать настраиваемый фильтр авторизации, который проверяет утверждение идентификатора компании текущего принципала?   -  person boosts    schedule 27.01.2015


Ответы (2)


Вот пользовательский фильтр авторизации, который вы можете использовать

using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;

public class AuthorizeAction : AuthorizeAttribute {

    public string CompanyId;

    protected override bool IsAuthorized(HttpActionContext actionContext) {


        if (String.IsNullOrEmpty(CompanyId))
        {
            var routeData = actionContext.Request.GetRouteData();
            var myId = routeData.Values["CompanyId"] as string;
            CompanyId = myId;
        }

        var user = actionContext.RequestContext.Principal as ClaimsPrincipal;

        if (user == null || !user.Identity.IsAuthenticated)
            return false;

        if (user.Claims.Any(claim => claim.Type.Equals("CompanyId") && claim.Value.Equals(CompanyId)))
            return true;

        return false;

    }

}

Вы также можете украсить свое действие или контроллер ниже, если хотите, чтобы только одна компания имела доступ к действию или контроллеру.

[AuthorizeAction(CompanyId = "1234")]
person boosts    schedule 27.01.2015

См. подход в https://github.com/AzureADSamples/NativeClient-DotNet/blob/master/TodoListService/Controllers/TodoListController.cs — вместо «области действия» вы можете использовать собственный тип утверждения.

person vibronet    schedule 26.01.2015
comment
Это означало бы необходимость реализации во многих контроллерах. Использование [Авторизация] невозможно? Спасибо - person Dave New; 27.01.2015
comment
Вы абсолютно правы, я только что указал вам на код для проверки входящего пользовательского утверждения, но если бы вы реализовали его как есть, его нельзя было бы использовать повторно. [Авторизовать] не поддерживает утверждения, однако вы всегда можете написать свой собственный атрибут. Пример пользовательского фильтра, выполняющего арифметические действия с утверждениями: github.com/AzureADSamples/ - person vibronet; 27.01.2015