[英]Get IPrincipal from OAuth Bearer Token in OWIN
我已使用OWIN成功将OAuth添加到我的WebAPI 2项目中。 我收到令牌,可以在HTTP Header中使用它们来访问资源。
现在,我想在其他通道上使用这些令牌进行身份验证,而不是为OWIN模板制作的标准HTTP请求。 例如,我正在使用WebSockets,其中客户端必须发送OAuth承载令牌进行身份验证。
在服务器端,我通过WebSocket接收令牌。 但是,我现在如何将此令牌放入OWIN管道以从中提取IPrincipal和ClientIdentifier? 在WebApi 2模板中,所有这些都是为我抽象的,因此我无需做任何事情来使其工作。
所以,基本上, 我将令牌作为字符串,并希望使用OWIN来访问该令牌中编码的用户信息。
提前感谢您的帮助。
我在这篇博客文章中找到了解决方案的一部分: http : //leastprivilege.com/2013/10/31/retrieving-bearer-tokens-from-alternative-locations-in-katanaowin/
所以我创建了自己的Provider,如下所示:
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"];
...
}
默认情况下,OWIN使用ASP.NET机器密钥数据保护来保护在IIS上托管时的OAuth访问令牌。 您可以在System.Web.dll中使用MachineKey类来取消保护令牌。
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);
}
除了johnny-qian的回答,使用这种方法更好的是创建DataProtector。 johnny-qian回答,取决于IIS并在自托管方案上失败。
using Microsoft.Owin.Security.DataProtection;
var dataProtector = app.CreateDataProtector(new string[] {
typeof(OAuthAuthorizationServerMiddleware).Namespace,
"Access_Token",
"v1"
});
您的令牌是什么,它是加密字符串还是格式化字符串,它的格式是什么?
我的代码:
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总是为空。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.