Подтвердить что ты не робот

Получите IPrincipal от токена носителя OAuth в OWIN

Я успешно добавил OAuth к моему проекту WebAPI 2 с использованием OWIN. Я получаю токены и могу использовать их в заголовке HTTP для доступа к ресурсам.

Теперь я хочу использовать эти токены также на других каналах для аутентификации, которые не являются стандартными HTTP-запросами, для которых создан шаблон OWIN. Например, я использую WebSockets, где клиент должен отправить токен-маркер OAuth для аутентификации.

На стороне сервера я получаю токен через WebSocket. Но как я могу теперь поместить этот токен в конвейер OWIN, чтобы извлечь из него IPrincipal и ClientIdentifier? В шаблоне WebApi 2 все это абстрагировано для меня, поэтому мне нечего делать, чтобы заставить его работать.

Итак, в основном, У меня есть токен в виде строки и вы хотите использовать OWIN для доступа к информации пользователя, закодированной в этом токене.

Заранее спасибо за помощь.

4b9b3361

Ответ 1

Я нашел часть решения в этом блоге: http://leastprivilege.com/2013/10/31/retrieving-bearer-tokens-from-alternative-locations-in-katanaowin/

Итак, я создал свой собственный провайдер следующим образом:

public class QueryStringOAuthBearerProvider : OAuthBearerAuthenticationProvider
{
    public override Task RequestToken(OAuthRequestTokenContext context)
    {
        var value = context.Request.Query.Get("access_token");

        if (!string.IsNullOrEmpty(value))
        {
            context.Token = value;
        }

        return Task.FromResult<object>(null);
    }
}

Затем мне нужно было добавить его в мое приложение в Startup.Auth.cs, как это:

OAuthBearerOptions = new OAuthBearerAuthenticationOptions()
{
   Provider = new QueryStringOAuthBearerProvider(),
   AccessTokenProvider = new AuthenticationTokenProvider()
   {
       OnCreate = create,
       OnReceive = receive
   },
};

app.UseOAuthBearerAuthentication(OAuthBearerOptions);

С помощью настраиваемого AuthenticationTokenProvider я могу извлечь все остальные значения из токена в начале конвейера:

public static Action<AuthenticationTokenCreateContext> create = new Action<AuthenticationTokenCreateContext>(c =>
{
    c.SetToken(c.SerializeTicket());
});

public static Action<AuthenticationTokenReceiveContext> receive = new Action<AuthenticationTokenReceiveContext>(c =>
{
    c.DeserializeTicket(c.Token);
    c.OwinContext.Environment["Properties"] = c.Ticket.Properties;
});

И теперь, например, в моем WebSocket Hander, я могу получить ClientId и другие, как это:

IOwinContext owinContext = context.GetOwinContext();
if (owinContext.Environment.ContainsKey("Properties"))
{
    AuthenticationProperties properties = owinContext.Environment["Properties"] as AuthenticationProperties;
    string clientId = properties.Dictionary["clientId"];
...
 }

Ответ 2

По умолчанию OWIN использует защиту данных машинного ключа ASP.NET для защиты токена доступа OAuth при размещении в IIS. Вы можете использовать класс MachineKey в System.Web.dll для снятия защиты с токенов.

public class MachineKeyProtector : IDataProtector
{
    private readonly string[] _purpose =
    {
        typeof(OAuthAuthorizationServerMiddleware).Namespace,
        "Access_Token",
        "v1"
    };

    public byte[] Protect(byte[] userData)
    {
       throw new NotImplementedException();
    }

    public byte[] Unprotect(byte[] protectedData)
    {
        return System.Web.Security.MachineKey.Unprotect(protectedData, _purpose);
    }
}

Затем создайте свойство TicketDataFormat, чтобы получить объект AuthenticationTicket, где вы можете получить свойство ClaimsIdentity и AuthenticationProperties.

var access_token="your token here";
var secureDataFormat = new TicketDataFormat(new MachineKeyProtector());
AuthenticationTicket ticket = secureDataFormat.Unprotect(access_token);

Чтобы снять защиту с других токенов OAuth, вам просто нужно изменить содержимое _purpose. Для получения дополнительной информации см. Раздел OAuthAuthorizationServerMiddleware: http://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Security.OAuth/OAuthAuthorizationServerMiddleware.cs

if (Options.AuthorizationCodeFormat == null)
{
    IDataProtector dataProtecter = app.CreateDataProtector(
        typeof(OAuthAuthorizationServerMiddleware).FullName,
        "Authentication_Code", "v1");

    Options.AuthorizationCodeFormat = new TicketDataFormat(dataProtecter);
}
if (Options.AccessTokenFormat == null)
{
    IDataProtector dataProtecter = app.CreateDataProtector(
        typeof(OAuthAuthorizationServerMiddleware).Namespace,
        "Access_Token", "v1");
    Options.AccessTokenFormat = new TicketDataFormat(dataProtecter);
}
if (Options.RefreshTokenFormat == null)
{
    IDataProtector dataProtecter = app.CreateDataProtector(
        typeof(OAuthAuthorizationServerMiddleware).Namespace,
        "Refresh_Token", "v1");
    Options.RefreshTokenFormat = new TicketDataFormat(dataProtecter);
}

Ответ 3

в дополнение к ответу johnny-qian, используя этот метод, лучше создать DataProtector. johnny-qian ответ, зависит от IIS и сбоя в самообслуживаемых сценариях.

using Microsoft.Owin.Security.DataProtection;
var dataProtector = app.CreateDataProtector(new string[]   {
     typeof(OAuthAuthorizationServerMiddleware).Namespace,
     "Access_Token",
     "v1"
});

Ответ 4

Каков ваш токен, например, это строка шифрования или форматированная строка, какой формат?

Я мой код:

public static Action<AuthenticationTokenReceiveContext> receive = new Action<AuthenticationTokenReceiveContext>(c =>
{
        if (!string.IsNullOrEmpty(c.Token))
        {

            c.DeserializeTicket(c.Token);
            //c.OwinContext.Environment["Properties"] = c.Ticket.Properties;
        }
});

Список c.Ticket всегда равен нулю.