【问题标题】:IdentityServer3 Refresh Token - Where to invoke the refreshIdentityServer3 Refresh Token - 在哪里调用刷新
【发布时间】:2017-12-30 15:06:36
【问题描述】:

我正在开发一个使用 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 看了两个例子,但是使用resourceowner flow for openid 似乎不是正确的方法。 MVC代码流依赖User还是有原则的,但是资源授权中我的声明都是空的。

编辑: 好的,所以如果我在 AuthorizationCodeReceived 中将 AuthenticationTicket.Properties.ExpiresUtc 设置为空,它会将其设置为空,然后将其设置为 30 天而不是 5 分钟(我搜索了武士刀和身份服务器源代码,但是找不到它在哪里设置这个值),我可以忍受,但希望它与它是“会话”的浏览器相同

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

【问题讨论】:

  • context.ReplaceIdentity() 的调用是否足以替换cookie?

标签: owin openid


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2016-07-06
    • 2019-05-02
    • 2015-12-29
    • 2022-01-04
    • 2021-03-07
    • 2019-02-18
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多