CodeVerification Cookie 在 Edge 和 Chrome 中消失
Posted
技术标签:
【中文标题】CodeVerification Cookie 在 Edge 和 Chrome 中消失【英文标题】:CodeVerification Cookie disappears in Edge and Chrome 【发布时间】:2021-09-27 23:28:10 【问题描述】:.NET framework 4.6.1 网站使用 OIDC 身份验证 (Microsoft.Owin.Security.OpenIdConnect 4.1.0) 作为身份验证的一部分,我包括“code_challenge”。下面的代码就是基于这个example。
RedirectToIdentityProvider = n =>
//ProcessCertificateValidation();
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
if (AppSettingsKey.AuthCodeChallangeEnabled.Enabled)
// generate code verifier and code challenge
var codeVerifier = CryptoRandom.CreateUniqueId(32);
string codeChallenge;
using (var sha256 = SHA256.Create())
var challengeBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(codeVerifier));
codeChallenge = Base64UrlEncoder.Encode(challengeBytes);
// set code_challenge parameter on authorization request
n.ProtocolMessage.Parameters.Add("code_challenge", codeChallenge);
n.ProtocolMessage.Parameters.Add("code_challenge_method", "S256");
// remember code verifier in cookie (adapted from OWIN nonce cookie)
RememberCodeVerifier(n, codeVerifier);
if (AppSettingsKey.MultiFactorAuthEnabled.Enabled)
n.ProtocolMessage.AcrValues = authCfg.AcrValues ?? n.ProtocolMessage.AcrValues;
logger.Debug("OIDC-Notification: RedirectToIdentityProvider Called");
//if signing out, add the id_token_hint
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
logger.Debug(" RequestType=" + OpenIdConnectRequestType.Logout);
var idTokenHint = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenHint != null)
logger.Debug(" IdTokenHint got from n.OwinContext.Authentication.User");
n.ProtocolMessage.IdTokenHint = idTokenHint.Value;
logger.Debug(" IdTokenHint=" + n?.ProtocolMessage?.IdTokenHint);
return Task.CompletedTask;
,
我确认“codeVerifierCookie”已发送。
AuthorizationCodeReceived = async n =>
logger.Debug("OIDC-Notification: AuthorizationCodeReceived Called");
logger.Debug(" Code=" + n.Code);
logger.Debug(" AuthenticationType=" + n.Options.AuthenticationType);
if (authCfg.DiscoverEndpoints)
var disco = await n.Options.ConfigurationManager.GetConfigurationAsync(n.OwinContext.Request.CallCancelled);
authCfg.TokenEndpoint = disco.TokenEndpoint;
authCfg.UserinfoEndpoint = disco.UserInfoEndpoint;
authCfg.EndsessionEndpoint = disco.EndSessionEndpoint;
//authCfg.RevocationEndpoint = disco.RevocationEndpoint;
authCfg.WebKeySetEndpoint = disco.JwksUri;
if (AppSettingsKey.AuthCodeChallangeEnabled.Enabled)
var codeVerifier = RetrieveCodeVerifier(n);
// attach code_verifier
n.TokenEndpointRequest.SetParameter("code_verifier", codeVerifier);
var requestMessage = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Post, authCfg.TokenEndpoint);
requestMessage.Content = new System.Net.Http.FormUrlEncodedContent(n.TokenEndpointRequest.Parameters);
var responseMessage = await n.Options.Backchannel.SendAsync(requestMessage);
responseMessage.EnsureSuccessStatusCode();
var responseContent = await responseMessage.Content.ReadAsStringAsync();
Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectMessage message = new Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectMessage(responseContent);
logger.Debug(" IdToken=" + message.IdToken);
logger.Debug(" AccessToken=" + message.AccessToken);
n.HandleCodeRedemption(message);
,
问题是当尝试检索“codeVerifierCookie”时它不存在,当尝试登录 Edge 或 Chrome(在 Firefox 上)时。
以下是用于发送、检索和获取验证码的方法。 CookieManager 配置为Microsoft.Owin.Host.SystemWeb.SystemWebChunkingCookieManager()
。
private void RememberCodeVerifier(RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> n, string codeVerifier)
var properties = new AuthenticationProperties();
properties.Dictionary.Add("cv", codeVerifier);
n.Options.CookieManager.AppendResponseCookie(
n.OwinContext,
GetCodeVerifierKey(n.ProtocolMessage.State),
Convert.ToBase64String(Encoding.UTF8.GetBytes(n.Options.StateDataFormat.Protect(properties))),
new CookieOptions
SameSite = SameSiteMode.None,
HttpOnly = true,
Secure = n.Request.IsSecure,
Expires = DateTime.UtcNow + n.Options.ProtocolValidator.NonceLifetime
);
private string RetrieveCodeVerifier(AuthorizationCodeReceivedNotification n)
string key = GetCodeVerifierKey(n.ProtocolMessage.State);
string codeVerifierCookie = n.Options.CookieManager.GetRequestCookie(n.OwinContext, key);
if (codeVerifierCookie != null)
var cookieOptions = new CookieOptions
SameSite = SameSiteMode.None,
HttpOnly = true,
Secure = n.Request.IsSecure
;
n.Options.CookieManager.DeleteCookie(n.OwinContext, key, cookieOptions);
var cookieProperties = n.Options.StateDataFormat.Unprotect(Encoding.UTF8.GetString(Convert.FromBase64String(codeVerifierCookie)));
cookieProperties.Dictionary.TryGetValue("cv", out var codeVerifier);
return codeVerifier;
private string GetCodeVerifierKey(string state)
using (var hash = SHA256.Create())
return OpenIdConnectAuthenticationDefaults.CookiePrefix + "cv." + Convert.ToBase64String(hash.ComputeHash(Encoding.UTF8.GetBytes(state)));
为什么当我尝试从 Edge 或 Chrome 登录时“codeVerifierCookie”丢失?可能是一些默认设置还是我的设置缺少某些东西?为什么它可以在 Firefox 上运行?
感谢您阅读我的帖子,我欢迎您就这个问题提出任何意见。
【问题讨论】:
【参考方案1】:您在测试应用时是否使用过 HTTPS?声明 SameSite=None
的 Cookie 也必须标记为 Secure
。我认为这个问题可能与同一站点 cookie 设置有关。
我发现a thread和你的问题一样,你可以参考一下。此外,还有a detailed article关于在 ASP.NET 中使用 SameSite cookie,您也可以查看它以获取更多信息。
【讨论】:
这正是问题所在。出于某种原因,Firefox 不需要 cookie 来保证安全。您认为将此代码验证程序 cookie 上的 Secure 属性设置为始终为真是正确的操作吗?谢谢你的回答。 我认为你需要在SameSite=None
时设置Secure
并使用HTTPS。以上是关于CodeVerification Cookie 在 Edge 和 Chrome 中消失的主要内容,如果未能解决你的问题,请参考以下文章