问题描述
我有一个MVC .NET Core 3.1应用程序,该应用程序使用Open ID connect进行身份验证并将身份和令牌存储在cookie中。在应用程序执行某些API请求时,需要刷新令牌。我订阅ValidatePrincipal事件并在那里刷新令牌。该请求正常,但由于某些原因未更新cookie。
Startup.cs:
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
options.OnAppendCookie = (e) =>
{
e.CookieOptions.Domain = <some domain>
};
});
...
.AddCookie(options =>
{
options.ExpireTimeSpan = TimeSpan.FromDays(30);
options.Cookie.Domain = <some domain>;
options.Cookie.IsEssential = true;
options.Cookie.Name = <some name>
options.EventsType = typeof(CookieAuthEvents);
})
CookieAuthEvents.cs(省略构造函数,成员声明和日志记录):
public override async Task ValidatePrincipal(CookieValidatePrincipalContext context)
{
if (context.Principal.Identity.IsAuthenticated)
{
var Now = DateTime.UtcNow;
var tokenExpiration = context.Properties.GetTokenExpiration();
if (Now > tokenExpiration)
{
await UpdateCookies(context);
}
}
}
private async Task UpdateCookies(CookieValidatePrincipalContext context)
{
var refreshToken = context.Properties.GetTokenValue(OpenIdConnectGrantTypes.RefreshToken);
if (String.IsNullOrEmpty(refreshToken))
{
return;
}
var response = await GetTokenClient().RequestRefreshTokenAsync(refreshToken);
if (!response.IsError)
{
WriteCookies(context,response);
}
else
{
context.RejectPrincipal();
}
}
private void WriteCookies(CookieValidatePrincipalContext context,TokenResponse response)
{
var tokens = new List<AuthenticationToken>
{
new AuthenticationToken
{
Name = OpenIdConnectParameterNames.IdToken,Value = response.IdentityToken
},new AuthenticationToken
{
Name = OpenIdConnectParameterNames.Accesstoken,Value = response.Accesstoken
},new AuthenticationToken
{
Name = OpenIdConnectParameterNames.RefreshToken,Value = response.RefreshToken
},new AuthenticationToken
{
Name = OpenIdConnectParameterNames.TokenType,Value = response.TokenType
}
};
var expiresAt = DateTime.UtcNow.AddSeconds(response.ExpiresIn);
tokens.Add(new AuthenticationToken
{
Name = "expires_at",Value = expiresAt.ToString("o",CultureInfo.InvariantCulture)
});
var newPrincipal = GetNewPrincipal(context);
context.ReplacePrincipal(newPrincipal);
context.Properties.Storetokens(tokens);
context.ShouldRenew = true;
}
private static ClaimsPrincipal GetNewPrincipal(CookieValidatePrincipalContext context)
{
var claims = context.Principal.Claims.Select(c => new Claim(c.Type,c.Value)).ToList();
var authTimeClaim = claims.FirstOrDefault(claim => claim.Type.Same("auth_time"));
if (authTimeClaim != null)
{
claims.Remove(authTimeClaim);
}
claims.Add(new Claim("auth_time",DateTime.UtcNow.UnixTimestamp().ToString()));
return new ClaimsPrincipal(new ClaimsIdentity(claims,context.Principal.Identity.AuthenticationType));
}
主要问题是,这在本地工作得很好。所有调用均正常,Cookie正确刷新。但是,当从开发机运行应用程序(我们将其托管在Azure App Service中)时,RequestRefreshTokenAsync调用成功,但是cookie并未更新,因此所有后续调用均使用旧令牌进行,导致400 invalid_grant错误。所以基本上我在日志中看到的是:
- RequestRefreshTokenAsync成功。旧的refresh_token用于获取新的
- ValidatePrincipal成功。这里的cookie应该被重写(包括一个新的refresh_token)
- 下一个请求-RequestRefreshTokenAsync失败。使用了旧版的refresh_token(即使它无效)。
我尝试使用cookie配置并将信号灯和锁放在ValidatePrincipal方法中,但是没有一个起作用。
有人知道会导致什么的原因吗?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)