简体   繁体   English

从OWIN中的OAuth Bearer Token获取IPrincipal

[英]Get IPrincipal from OAuth Bearer Token in OWIN

I have successfully added OAuth to my WebAPI 2 project using OWIN. 我已使用OWIN成功将OAuth添加到我的WebAPI 2项目中。 I receive tokens and can use them in the HTTP Header to access resources. 我收到令牌,可以在HTTP Header中使用它们来访问资源。

Now I want to use those tokens also on other channels for authentication that are not the standard HTTP requests that the OWIN template is made for. 现在,我想在其他通道上使用这些令牌进行身份验证,而不是为OWIN模板制作的标准HTTP请求。 For example, I am using WebSockets where the client has to send the OAuth Bearer Token to authenticate. 例如,我正在使用WebSockets,其中客户端必须发送OAuth承载令牌进行身份验证。

On the server side, I receive the token through the WebSocket. 在服务器端,我通过WebSocket接收令牌。 But how can I now put this token into the OWIN pipeline to extract the IPrincipal and ClientIdentifier from it? 但是,我现在如何将此令牌放入OWIN管道以从中提取IPrincipal和ClientIdentifier? In the WebApi 2 template, all this is abstracted for me, so there is nothing I have to do to make it work. 在WebApi 2模板中,所有这些都是为我抽象的,因此我无需做任何事情来使其工作。

So, basically, I have the token as a string and want to use OWIN to access the user information encoded in that token. 所以,基本上, 我将令牌作为字符串,并希望使用OWIN来访问该令牌中编码的用户信息。

Thank you in advance for the help. 提前感谢您的帮助。

I found a part of the solution in this blog post: http://leastprivilege.com/2013/10/31/retrieving-bearer-tokens-from-alternative-locations-in-katanaowin/ 我在这篇博客文章中找到了解决方案的一部分: http//leastprivilege.com/2013/10/31/retrieving-bearer-tokens-from-alternative-locations-in-katanaowin/

So I created my own Provider as follows: 所以我创建了自己的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);
    }
}

Then I needed to add it to my App in Startup.Auth.cs like this: 然后我需要在Startup.Auth.cs中将它添加到我的应用程序中,如下所示:

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

app.UseOAuthBearerAuthentication(OAuthBearerOptions);

With a custom AuthenticationTokenProvider, I can retrieve all other values from the token early in the pipeline: 使用自定义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;
});

And now, for example in my WebSocket Hander, I can retrieve ClientId and others like this: 现在,例如在我的WebSocket Hander中,我可以检索ClientId和其他类似的东西:

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

By default, OWIN use ASP.NET machine key data protection to protect the OAuth access token when hosted on IIS. 默认情况下,OWIN使用ASP.NET机器密钥数据保护来保护在IIS上托管时的OAuth访问令牌。 You can use MachineKey class in System.Web.dll to unprotect the tokens. 您可以在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);
    }
}

Then, construct a TicketDataFormat to get the AuthenticationTicket object where you can get the ClaimsIdentity and AuthenticationProperties. 然后,构造一个TicketDataFormat以获取AuthenticationTicket对象,您可以在其中获取ClaimsIdentity和AuthenticationProperties。

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

To unprotect other OAuth tokens, you just need to change the _purpose content. 要取消保护其他OAuth令牌,您只需更改_purpose内容即可。 For detailed information, see OAuthAuthorizationServerMiddleware class here: http://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Security.OAuth/OAuthAuthorizationServerMiddleware.cs 有关详细信息,请参阅此处的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);
}

in addition to johnny-qian answer, using this method is better to create DataProtector. 除了johnny-qian的回答,使用这种方法更好的是创建DataProtector。 johnny-qian answer, depends on IIS and fails on self-hosted scenarios. johnny-qian回答,取决于IIS并在自托管方案上失败。

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

What is your token like, is it an encrypt string or a formatted string, what is it format? 您的令牌是什么,它是加密字符串还是格式化字符串,它的格式是什么?

I my code: 我的代码:

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;
        }
});

The c.Ticket is always null. c.Ticket总是为空。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM