我正在开发一个使用OpenID和IdentityServer3的MVC应用程序。
背景:
我遇到的问题是,当身份验证Cookie超时时,我需要使用刷新令牌生成一个新令牌。
我能够登录并接收AuthorizationCodeReceived通知,我用它来请求授权代码并检索我存储在AuthenticationTicket声明中的RefreshToken。
我尝试添加逻辑来检查和刷新身份验证:
添加过滤器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);
}
}
});
答案 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);