IdentityServer3刷新令牌 - 在何处调用刷新

时间:2017-07-24 21:45:10

标签: owin openid

我正在开发一个使用OpenID和IdentityServer3的MVC应用程序。

背景:

我遇到的问题是,当身份验证Cookie超时时,我需要使用刷新令牌生成一个新令牌。

我能够登录并接收AuthorizationCodeReceived通知,我用它来请求授权代码并检索我存储在AuthenticationTicket声明中的RefreshToken。

我尝试添加逻辑来检查和刷新身份验证:

  • CookieAuthenticationProvider.OnValidateIdentity - 这适用于 刷新,我能够更新cookie,但是在cookie过期后不会调用它。
  • 在ResourceAuthorizationManager.CheckAccessAsync的开头添加代码 - 这不起作用,因为标识为空,我无法检索刷新令牌声明。
  • 添加过滤器Filter for MVC,但我无法弄清楚要添加什么作为WebAPI的HttpResponseMessage。

    public const string RefreshTokenKey = "refresh_token";
    public const string ExpiresAtKey = "expires_at";
    private const string AccessTokenKey = "access_token";
    
    private static bool CheckAndRefreshTokenIfRequired(ClaimsIdentity id, out ClaimsIdentity identity)
    {
        if (id == null)
        {
            identity = null;
            return false;
        }
    
        if (id.Claims.All(x => x.Type != ExpiresAtKey) || id.Claims.All(x => x.Type != RefreshTokenKey))
        {
            identity = id;
            return false;
        }
        //Check if the access token has expired
        var expiresAt = DateTime.Parse(id.FindFirstValue(ExpiresAtKey));
        if ((expiresAt - DateTime.Now.ToLocalTime()).TotalSeconds < 0)
        {
            var client = GetClient();
    
            var refreshToken = id.FindFirstValue(RefreshTokenKey);
    
            var tokenResponse = client.RequestRefreshTokenAsync(refreshToken).Result;
    
            if (tokenResponse.IsError)
            {
                throw new Exception(tokenResponse.Error);
            }
    
            var result = from c in id.Claims
                where c.Type != AccessTokenKey &&
                      c.Type != RefreshTokenKey &&
                      c.Type != ExpiresAtKey
                select c;
    
            var claims = result.ToList();
    
            claims.Add(new Claim(AccessTokenKey, tokenResponse.AccessToken));
            claims.Add(new Claim(ExpiresAtKey, DateTime.Now.AddSeconds(tokenResponse.ExpiresIn).ToLocalTime().ToString()));
            claims.Add(new Claim(RefreshTokenKey, tokenResponse.RefreshToken));
    
    
            identity = new ClaimsIdentity(claims, id.AuthenticationType);
            return true;
        }
        identity = id;
        return false;
    }
    

链接:

How would I use RefreshTokenHandler?

Identity Server3 documentation 看看这两个例子,但是对openid使用resourceowner流似乎不是正确的方法。 MVC代码流依赖于仍然具有原则的用户,但我的声明在资源授权中都是空的。

编辑: 好吧,如果我在AuthorizationCodeReceived中将AuthenticationTicket.Properties.ExpiresUtc设置为null,则将其设置为null然后将其设置为30天而不是5分钟(我搜索了katana和身份服务器源代码但是无法找到它设置此值的位置),我可以使用它,但更喜欢它与浏览器相同,它是“会话”

            app.UseCookieAuthentication(new CookieAuthenticationOptions()
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            CookieManager = new SystemWebChunkingCookieManager(),

            Provider = new CookieAuthenticationProvider()
            { 
              OnValidateIdentity  = context =>
              {
                  ClaimsIdentity i;
                  if (CheckAndRefreshTokenIfRequired(context.Identity, out i))
                  {
                      context.ReplaceIdentity(i);
                  }
                  return Task.FromResult(0);
              }
            }
        });

1 个答案:

答案 0 :(得分:1)

问题在于AuthorizationCodeRecieved通知我从原始票证传递了属性,其中为授权代码的Expires设置了超时。更改了代码以传递null以解决问题并允许CookieAuthenticationHandler.ApplyResponseGrantAsync到传递自己的属性。

var claimsIdentity = new ClaimsIdentity(id.Claims, n.AuthenticationTicket.Identity.AuthenticationType, "name", "role");
n.AuthenticationTicket = new AuthenticationTicket(claimsIdentity, null);