Получите IPrincipal от токена носителя OAuth в OWIN
Я успешно добавил OAuth к моему проекту WebAPI 2 с использованием OWIN. Я получаю токены и могу использовать их в заголовке HTTP для доступа к ресурсам.
Теперь я хочу использовать эти токены также на других каналах для аутентификации, которые не являются стандартными HTTP-запросами, для которых создан шаблон OWIN. Например, я использую WebSockets, где клиент должен отправить токен-маркер OAuth для аутентификации.
На стороне сервера я получаю токен через WebSocket. Но как я могу теперь поместить этот токен в конвейер OWIN, чтобы извлечь из него IPrincipal и ClientIdentifier? В шаблоне WebApi 2 все это абстрагировано для меня, поэтому мне нечего делать, чтобы заставить его работать.
Итак, в основном, У меня есть токен в виде строки и вы хотите использовать OWIN для доступа к информации пользователя, закодированной в этом токене.
Заранее спасибо за помощь.
Ответы
Ответ 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 всегда равен нулю.