【发布时间】: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?