首页 文章

从OWIN中的OAuth Bearer Token获取IPrincipal

提问于
浏览
31

我已使用OWIN成功将OAuth添加到我的WebAPI 2项目中 . 我收到令牌,可以在HTTP Header中使用它们来访问资源 .

现在,我想在其他通道上使用这些令牌进行身份验证,而不是为OWIN模板制作的标准HTTP请求 . 例如,我正在使用WebSockets,其中客户端必须发送OAuth承载令牌进行身份验证 .

在服务器端,我通过WebSocket接收令牌 . But how can I now put this token into the OWIN pipeline to extract the IPrincipal and ClientIdentifier from it? 在WebApi 2模板中,所有这些都是为我抽象的,所以我无需做任何事情来使其工作 .

基本上, I have the token as a string and want to use OWIN to access the user information encoded in that token.

提前感谢您的帮助 .

4 回答

  • 1

    我在这篇博客文章中找到了解决方案的一部分: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"];
    ...
     }
    
  • 0

    默认情况下,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);
    }
    
  • 9

    除了 johnny-qian 回答,使用此方法最好创建DataProtector . johnny-qian 答案,取决于IIS并在自托管方案上失败 .

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

    您的令牌是什么,它是加密字符串还是格式化字符串,它的格式是什么?

    我的代码:

    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总是为空 .

相关问题