OAuth: ASP.NET Web API User.Identity не загружает утверждения, установленные поставщиком токенов аутентификации

Я использую аутентификацию носителя OAuth, настроенную следующим образом в Startup.cs:

        OAuthBearerAuthenticationOptions oAuthBearerOptions = 
            new OAuthBearerAuthenticationOptions
            {
                AccessTokenProvider = new AccessTokenProvider(),
                AuthenticationMode = AuthenticationMode.Active
            };
        app.UseOAuthBearerAuthentication(oAuthBearerOptions);

... где AccessTokenProvider реализован как:

public class AccessTokenProvider : AuthenticationTokenProvider
{
    public override async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
    {
        // Internal logic to get data needed for building identity...

        // Create claims identity
        ClaimsIdentity identity = new ClaimsIdentity(identityName);
        identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, nameIdentifier));
        // Add other claims

        // Set claims identity
        context.SetTicket(new AuthenticationTicket(identity, new AuthenticationProperties()));
    }
}

Если я установлю точку останова в конце ReceiveAsync, я могу убедиться, что идентификатор построен правильно (имеет утверждения) и что SetTicket достигнут.

Но когда я пытаюсь получить доступ к удостоверению из контроллера веб-API:

public abstract class BaseStorageController : ApiController
{
    protected IStorageService StorageService;

    protected BaseStorageController(IStorageServiceFactory storageServiceFactory)
    {
        StorageService = storageServiceFactory.CreateStorageService(User.Identity as ClaimsIdentity);
    }

}

... список требований к личности пуст!

Что может быть причиной этого?

Боковое примечание: я не знаю, связано ли это, но я использую Castle Windsor в качестве контейнера IOC для внедрения зависимостей в мои контроллеры (в приведенном выше случае IStorageServiceFactory). Вышеупомянутое, казалось, сработало (претензии не были пустыми) до того, как я добавил это. Однако я не использую CW для управления чем-либо, связанным с аутентификацией. Вот мой установщик CW для контроллеров api:

public class ApiControllerInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(Classes.FromThisAssembly().BasedOn<ApiController>().LifestylePerWebRequest());
    }
}

person mayabelle    schedule 09.03.2015    source источник


Ответы (2)


Я нашел ответ. Это не было связано с внедрением зависимостей / инверсией управления. Я не уверен, как я думал, что это работало до добавления этого.

Проблема аналогична описанной здесь (но в моем случае решение другое): Пользователь (IPrincipal) недоступен в конструкторе ApiController с использованием Web Api 2.1 и Owin

В основном IPrincipal недоступен из конструктора контроллера api, поэтому нет никаких заявлений (пользователь еще не аутентифицирован). User.Identity доступен только из действий контроллера, но не из конструктора. Чтобы обойти эту проблему, я изменил реализацию базового контроллера на следующую:

public abstract class BaseStorageController : ApiController
{
    private readonly IStorageServiceFactory _storageServiceFactory;
    private IStorageService _storageService;

    protected BaseStorageController(IStorageServiceFactory storageServiceFactory)
    {
        _storageServiceFactory = storageServiceFactory;
    }

    protected IStorageService StorageService
    {
        get
        {
            if (_storageService == null)
            {
                _storageService = _storageServiceFactory.CreateStorageService(User.Identity as ClaimsIdentity);
            }
            return _storageService;
        }
    }
}

Поскольку доступ к StorageService осуществляется только из действий контроллера, User.Identity аутентифицируется и имеет утверждения, заполненные к моменту вызова StorageService геттера.

Надеюсь, это кому-то поможет!

person mayabelle    schedule 09.03.2015
comment
Спасибо!!! У меня проблема с конструктором длилась весь день, и я пробовал несколько разных реализаций authprovider. Это решило это. - person Rasmus Christensen; 08.05.2015

 protected IStorageService StorageService
{
    get
    {
        if (_storageService == null)
        {
            _storageService = _storageServiceFactory.CreateStorageService(User.Identity as ClaimsIdentity);
        }
        return _storageService;
    }
}

это не лучший подход для реализации DI

Намного лучше использовать инъекцию конструктора. Проверьте Внедрение конструктора в C # / Unity?, если вы не знакомы с Unity, следуйте этому ссылка, очень полезная: https://msdn.microsoft.com/en-us/library/dn223671(v=pandp.30).aspx

С Уважением

person Boris Malaichik    schedule 01.09.2015
comment
IPrincipal недоступен в конструкторе контроллера веб-API, что означает, что внедрение конструктора в этом случае не работает. - person lucuma; 13.01.2017