如何在OpenId中添加刷新令牌?UseOpenIdConnectAuthentication相关问题
无法获取RefreshToken的解决方案
问题根源
你在SecurityTokenValidated通知里找不到context.ProtocolMessage.RefreshToken,是因为RefreshToken仅在Authorization Code Flow的Token响应阶段返回,而SecurityTokenValidated是在ID Token验证完成后触发的,此时ProtocolMessage已经不包含RefreshToken了。
修复步骤
1. 确保启用Authorization Code Flow
首先确认你的OpenIdConnectAuthenticationOptions设置了正确的响应类型,只有包含code的响应类型才会触发Authorization Code Flow,进而返回RefreshToken:
new OpenIdConnectAuthenticationOptions { // 必须包含"code",Implicit Flow(仅"id_token")不支持RefreshToken ResponseType = "code id_token", Scope = "openid profile offline_access User.ReadBasic.All User.Read.All Directory.Read.All", // ... 其他配置 }
2. 在AuthorizationCodeReceived中捕获RefreshToken
添加AuthorizationCodeReceived通知,这个阶段是获取Token响应的时机,这里能拿到RefreshToken,将其存入AuthenticationTicket.Properties以便后续使用:
Notifications = new OpenIdConnectAuthenticationNotifications { AuthorizationCodeReceived = async context => { // 从ProtocolMessage中提取RefreshToken var refreshToken = context.ProtocolMessage.RefreshToken; if (!string.IsNullOrEmpty(refreshToken)) { // 存入Properties字典 context.AuthenticationTicket.Properties.Dictionary["refresh_token"] = refreshToken; } }, // 保留你原有的RedirectToIdentityProvider和SecurityTokenValidated逻辑 RedirectToIdentityProvider = (context) => { // ... 你的原有代码 return Task.FromResult(0); }, SecurityTokenValidated = async context => { // ... 你的原有代码 } }
3. 在SecurityTokenValidated中读取RefreshToken
现在可以从AuthenticationTicket.Properties中取出之前存储的RefreshToken:
SecurityTokenValidated = async context => { try { ClaimsIdentity claimsIdentity = context.AuthenticationTicket.Identity; if (claimsIdentity.IsAuthenticated) { // ... 你的原有代码 // 读取RefreshToken if (context.AuthenticationTicket.Properties.Dictionary.TryGetValue("refresh_token", out var refreshToken)) { // 可将其添加到Claims或存储到Cookie claimsIdentity.AddClaim(new System.Security.Claims.Claim("refresh_token", refreshToken)); } // ... 其他代码 } } catch (Exception ex) { // ... 你的原有异常处理 } }
额外检查项
- 确认你的身份提供商(如Azure AD)已配置允许颁发RefreshToken,且应用类型为Web应用/API(Native应用默认支持,Web应用需确保配置正确)。
- 在
RedirectToIdentityProvider中打印context.ProtocolMessage.Scope,确认offline_access确实被包含在请求的作用域中。
内容的提问来源于stack exchange,提问作者Sachit Murarka
相关产品推荐
相关产品推荐

