OWIN安全 - 如何实施的OAuth2刷新令牌 [英] OWIN Security - How to Implement OAuth2 Refresh Tokens

查看:1912
本文介绍了OWIN安全 - 如何实施的OAuth2刷新令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用附带的Visual Studio 2013的网页API 2模板有一些OWIN中间件做用户认证和喜欢。

OAuthAuthorizationServerOptions 我注意到的OAuth2服务器所交出出14天后到期令牌

  OAuthOptions =新OAuthAuthorizationServerOptions
 {
      TokenEndpointPath =新PathString(/ API /标记),
      供应商=新ApplicationOAuthProvider(PublicClientId,UserManagerFactory)
      AuthorizeEndpointPath =新PathString(/ API /帐号/ ExternalLogin),
      AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
      AllowInsecureHttp =真
 };

这是不适合我的最新项目。我想伸手短命bearer_tokens可以使用刷新一个 refresh_token

我已经做了很多谷歌搜索,并不能找到什么有用的。

这就是我设法多远就搞定了。现在我已经达到的地步跆拳道做我现在。

我已经写了 RefreshTokenProvider 实现 IAuthenticationTokenProvider 为每 RefreshTokenProvider OAuthAuthorizationServerOptions 类:

 公共类SimpleRefreshTokenProvider:IAuthenticationTokenProvider
    {
       私有静态ConcurrentDictionary<字符串,AuthenticationTicket> _refreshTokens =新ConcurrentDictionary<字符串,AuthenticationTicket>();        公共异步任务CreateAsync(AuthenticationTokenCreateContext上下文)
        {
            VAR GUID = Guid.NewGuid()的ToString()。
            _refreshTokens.TryAdd(GUID,context.Ticket);            //哈希?
            context.SetToken(GUID);
        }        公共异步任务ReceiveAsync(AuthenticationTokenReceiveContext上下文)
        {
            AuthenticationTicket票;            如果(_refreshTokens.TryRemove(context.Token,出票))
            {
                context.SetTicket(票);
            }
        }        公共无效创建(AuthenticationTokenCreateContext上下文)
        {
            抛出新NotImplementedException();
        }        公共无效接收(AuthenticationTokenReceiveContext上下文)
        {
            抛出新NotImplementedException();
        }
    }    //现在在我的Startup.Auth.cs
    OAuthOptions =新OAuthAuthorizationServerOptions
    {
        TokenEndpointPath =新PathString(/ API /标记),
        供应商=新ApplicationOAuthProvider(PublicClientId,UserManagerFactory)
        AuthorizeEndpointPath =新PathString(/ API /帐号/ ExternalLogin),
        AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(2),
        AllowInsecureHttp = TRUE,
        RefreshTokenProvider =新RefreshTokenProvider()//这是我的测试
    };

所以,现在当有人请求 bearer_token 现在我给一个 refresh_token ,这是伟大的。

所以,现在我该怎么使用这个refresh_token得到一个新的 bearer_token ,presumably我需要一个请求发送到我的令牌端点设置一些特定的HTTP头?

只是想大声在我键入......我应该处理refresh_token到期我的 SimpleRefreshTokenProvider ?如何将客户端获得一个新的 refresh_token

我真的可以用一些阅读材料/文档做的,因为我不想让这个错误,并希望遵循某种标准。


解决方案

只是实现我的OWIN服务与承载(在下面叫的access_token),并刷新令牌。我深知这是你可以使用不同的流量。所以,这取决于你想用你如何设置你的access_token和refresh_token到期时间的流动。

我将描述两个流入 A 在follwing(我建议你要什么有是流B):

A)的access_token和refresh_token的到期时间是一样的,因为它是每默认1200秒或20分钟。这个流程首先需要客户端发送的CLIENT_ID和登录数据client_secret得到一个的access_token,refresh_token和EXPIRATION_TIME。与refresh_token现在有可能获得20分钟(或任何你设置AccessTokenExpireTimeSpan在OAuthAuthorizationServerOptions到)一个新的access_token。对于和的access_token的refresh_token到期时间相同的原因,你的客户负责的到期时间之前得到一个新的access_token!例如。您的客户端可以发送刷新POST调用您的令牌端点与身体(注:你应该在生产中使用https)

<$p$p><$c$c>grant_type=refresh_token&client_id=xxxxxx&refresh_token=xxxxxxxx-xxxx-xxxx-xxxx-xxxxx

例如后得到一个新的令牌19分钟至prevent从过期的令牌。

B)您要为您的access_token短期到期并为您的refresh_token长期期满这个流程。让我们假设你设置的access_token在10秒( AccessTokenExpireTimeSpan = TimeSpan.FromSeconds(10))和refresh_token〜5分钟后过期的测试目的。现在,它涉及到了有趣的部分设置refresh_token的到期时间:

:你在SimpleRefreshTokenProvider类这样您createAsync功能做到这一点

  VAR GUID = Guid.NewGuid()的ToString();
        //复制属性并设置刷新令牌的使用寿命所需
        VAR refreshTokenProperties =新AuthenticationProperties(context.Ticket.Properties.Dictionary)
        {
            IssuedUtc = context.Ticket.Properties.IssuedUtc,
            ExpiresUtc = DateTime.UtcNow.AddMinutes(5)//设置DATETIME至5分钟
            // ExpiresUtc = DateTime.UtcNow.AddMonths(3)
        };
        / *创建一个5分钟的到期时间新票
         *包括背景票的价值观:所以我们
         *在这里做的是添加特性IssuedUtc和
         * ExpiredUtc的车票* /
        VAR refreshTokenTicket =新AuthenticationTicket(context.Ticket.Identity,refreshTokenProperties);        //保存新refreshTokenTicket至类型ConcurrentDictionary℃的局部变量;串,AuthenticationTicket&GT;
        //考虑只存储在手柄的散列
        RefreshTokens.TryAdd(GUID,refreshTokenTicket);
        context.SetToken(GUID);

现在您的客​​户端能够当的access_token 过期与一个refresh_token一个POST呼叫发送到您的令牌端点。通话的身体的一部分可能是这样的: <$c$c>grant_type=refresh_token&client_id=xxxxxx&refresh_token=xxxxxxxx-xxxx-xxxx-xxxx-xx

一个重要的事情是,你可能不仅希望在CreateAsync功能,而且在创建函数使用此code。所以,你应该考虑使用自己的功能(例如称为CreateTokenInternal)为上述code。
这里你可以找到不同的流的实现包括refresh_token流(但不设置refresh_token的到期时间)

<一个href=\"https://github.com/thinktecture/Thinktecture.IdentityModel/blob/master/samples/OAuth2/EmbeddedResourceOwnerFlowWithRefreshTokens/EmbeddedAuthorizationServer/Provider/SimpleRefreshTokenProvider.cs\">Here在GitHub上 IAuthenticationTokenProvider的一个样本实现(与设置refresh_token的到期时间)

我很抱歉,我不能帮助与比OAuth的规格和微软API文档进一步的材料。我会在这里发布的链接,但我的名声并不让我上传超过2链接....

我希望这可以帮助一些人试图实现与refresh_token到期时间不同,以ACCESS_TOKEN到期时间OAuth2.0的时候业余时间。我无法找到网页(除的thinktecture上面链接的那个)上的示例实现我花了几个小时的调查,直到它为我工作。

新信息:对我来说,我有两个不同的可能性,获得令牌。一个是接收到有效的access_token。在那里,我必须发送一个POST调用与格式应用程序/ x-WWW的形式urlen codeD包括以下数据

一个String体<$p$p><$c$c>client_id=YOURCLIENTID&grant_type=password&username=YOURUSERNAME&password=YOURPASSWORD

二是如果的access_token不再有效,我们可以尝试通过格式字符串体发送POST调用应用程序/ x-WWW的形式urlen codeD 通过以下数据<$c$c>grant_type=refresh_token&client_id=YOURCLIENTID&refresh_token=YOURREFRESHTOKENGUID

I am using the Web Api 2 template that comes with Visual Studio 2013 has some OWIN middleware to do User Authentication and the likes of.

In the OAuthAuthorizationServerOptions I noticed that the OAuth2 Server is setup to hand out tokens that expire in 14 days

 OAuthOptions = new OAuthAuthorizationServerOptions
 {
      TokenEndpointPath = new PathString("/api/token"),
      Provider = new ApplicationOAuthProvider(PublicClientId,UserManagerFactory) ,
      AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
      AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
      AllowInsecureHttp = true
 };

This is not suitable for my latest project. I would like to hand out short lived bearer_tokens that can be refreshed using a refresh_token

I have done lots of googling and can't find anything helpful.

So this is how far I have managed to get. I have now reached the point of "WTF do I now".

I have written a RefreshTokenProvider that implements IAuthenticationTokenProvider as per the RefreshTokenProvider property on OAuthAuthorizationServerOptions class:

    public class SimpleRefreshTokenProvider : IAuthenticationTokenProvider
    {
       private static ConcurrentDictionary<string, AuthenticationTicket> _refreshTokens = new ConcurrentDictionary<string, AuthenticationTicket>();

        public async Task CreateAsync(AuthenticationTokenCreateContext context)
        {
            var guid = Guid.NewGuid().ToString();


            _refreshTokens.TryAdd(guid, context.Ticket);

            // hash??
            context.SetToken(guid);
        }

        public async Task ReceiveAsync(AuthenticationTokenReceiveContext context)
        {
            AuthenticationTicket ticket;

            if (_refreshTokens.TryRemove(context.Token, out ticket))
            {
                context.SetTicket(ticket);
            }
        }

        public void Create(AuthenticationTokenCreateContext context)
        {
            throw new NotImplementedException();
        }

        public void Receive(AuthenticationTokenReceiveContext context)
        {
            throw new NotImplementedException();
        }
    }

    // Now in my Startup.Auth.cs
    OAuthOptions = new OAuthAuthorizationServerOptions
    {
        TokenEndpointPath = new PathString("/api/token"),
        Provider = new ApplicationOAuthProvider(PublicClientId,UserManagerFactory) ,
        AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
        AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(2),
        AllowInsecureHttp = true,
        RefreshTokenProvider = new RefreshTokenProvider() // This is my test
    };

So now when someone requests a bearer_token I am now sending a refresh_token, which is great.

So now how do I uses this refresh_token to get a new bearer_token, presumably I need to send a request to my token endpoint with some specific HTTP Headers set?

Just thinking out loud as I type... Should I handle refresh_token expiration in my SimpleRefreshTokenProvider? How would a client obtain a new refresh_token?

I could really do with some reading material / documentation because I don't want to get this wrong and would like to follow some sort of standard.

解决方案

Just implemented my OWIN Service with Bearer (called access_token in the following) and Refresh Tokens. My insight into this is that you can use different flows. So it depends on the flow you want to use how you set your access_token and refresh_token expiration times.

I will describe two flows A and B in the follwing (I suggest what you want to have is flow B):

A) expiration time of access_token and refresh_token are the same as it is per default 1200 seconds or 20 minutes. This flow needs your client first to send client_id and client_secret with login data to get an access_token, refresh_token and expiration_time. With the refresh_token it is now possible to get a new access_token for 20 minutes (or whatever you set the AccessTokenExpireTimeSpan in the OAuthAuthorizationServerOptions to). For the reason that the expiration time of access_token and refresh_token are the same, your client is responsible to get a new access_token before the expiration time! E.g. your client could send a refresh POST call to your token endpoint with the body (remark: you should use https in production)

grant_type=refresh_token&client_id=xxxxxx&refresh_token=xxxxxxxx-xxxx-xxxx-xxxx-xxxxx

to get a new token after e.g. 19 minutes to prevent the tokens from expiration.

B) in this flow you want to have a short term expiration for your access_token and a long term expiration for your refresh_token. Lets assume for test purpose you set the access_token to expire in 10 seconds (AccessTokenExpireTimeSpan = TimeSpan.FromSeconds(10)) and the refresh_token to 5 Minutes. Now it comes to the interesting part setting the expiration time of refresh_token: You do this in your createAsync function in SimpleRefreshTokenProvider class like this:

var guid = Guid.NewGuid().ToString();


        //copy properties and set the desired lifetime of refresh token
        var refreshTokenProperties = new AuthenticationProperties(context.Ticket.Properties.Dictionary)
        {
            IssuedUtc = context.Ticket.Properties.IssuedUtc,
            ExpiresUtc = DateTime.UtcNow.AddMinutes(5) //SET DATETIME to 5 Minutes
            //ExpiresUtc = DateTime.UtcNow.AddMonths(3) 
        };
        /*CREATE A NEW TICKET WITH EXPIRATION TIME OF 5 MINUTES 
         *INCLUDING THE VALUES OF THE CONTEXT TICKET: SO ALL WE 
         *DO HERE IS TO ADD THE PROPERTIES IssuedUtc and 
         *ExpiredUtc to the TICKET*/
        var refreshTokenTicket = new AuthenticationTicket(context.Ticket.Identity, refreshTokenProperties);

        //saving the new refreshTokenTicket to a local var of Type ConcurrentDictionary<string,AuthenticationTicket>
        // consider storing only the hash of the handle
        RefreshTokens.TryAdd(guid, refreshTokenTicket);            
        context.SetToken(guid);

Now your client is able to send a POST call with a refresh_token to your token endpoint when the access_token is expired. The body part of the call may look like this: grant_type=refresh_token&client_id=xxxxxx&refresh_token=xxxxxxxx-xxxx-xxxx-xxxx-xx

One important thing is that you may want to use this code not only in your CreateAsync function but also in your Create function. So you should consider to use your own function (e.g. called CreateTokenInternal) for the above code. Here you can find implementations of different flows including refresh_token flow(but without setting the expiration time of the refresh_token)

Here is one sample implementation of IAuthenticationTokenProvider on github (with setting the expiration time of the refresh_token)

I am sorry that I can't help out with further materials than the OAuth Specs and the Microsoft API Documentation. I would post the links here but my reputation doesn't let me post more than 2 links....

I hope this may help some others to spare time when trying to implement OAuth2.0 with refresh_token expiration time different to access_token expiration time. I couldn't find an example implementation on the web (except the one of thinktecture linked above) and it took me some hours of investigation until it worked for me.

New info: In my case I have two different possibilities to receive tokens. One is to receive a valid access_token. There I have to send a POST call with a String body in format application/x-www-form-urlencoded with the following data

client_id=YOURCLIENTID&grant_type=password&username=YOURUSERNAME&password=YOURPASSWORD

Second is if access_token is not valid anymore we can try the refresh_token by sending a POST call with a String body in format application/x-www-form-urlencoded with the following data grant_type=refresh_token&client_id=YOURCLIENTID&refresh_token=YOURREFRESHTOKENGUID

这篇关于OWIN安全 - 如何实施的OAuth2刷新令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆