使用 AD FS 4.0 (2016) 或更高版本获取新的刷新令牌
Posted
技术标签:
【中文标题】使用 AD FS 4.0 (2016) 或更高版本获取新的刷新令牌【英文标题】:Getting a new refresh token with AD FS 4.0 (2016) or higher 【发布时间】:2021-11-14 18:24:26 【问题描述】:我将 AD FS 2016 配置为支持通过 OAuth2/OpenID Connect 使用授权代码授予和 PKCE 对“本机应用程序”进行身份验证。我通过设置以下内容创建了一个依赖方并配置(用于测试目的)令牌生命周期:
Set-AdfsRelyingPartyTrust -TargetName MyRPT -IssueOAuthRefreshTokensTo AllDevices -TokenLifetime 3
Grant-AdfsApplicationPermission -ClientRoleIdentifier MyClient -ServerRoleIdentifier MyRPT -ScopeNames openid,profile,email
Set-AdfsProperty -SSOLifetime 7 -PersistenSsoEnabled $false
...这给了我在 3 分钟后过期的访问/ID 令牌和在 7(实际上是 14,见下文)分钟后过期的刷新令牌。我还禁用了持久 SSO,所以我没有得到会话 cookie。都很好。
身份验证成功后,我的客户端向 /oauth2/token 端点发出 POST 请求,并传递以下参数:
client_id:“我的客户” 代码:... redirect_uri: ... code_verifier: ... grant_type: "authorization_code"我收到以下有效回复:
"access_token": "...",
"token_type": "bearer",
"expires_in": 180,
"resource": "MyRPT",
"refresh_token": "...",
"refresh_token_expires_in": 419,
"scope": "email profile openid",
"id_token": "..."
太棒了。
然后在访问令牌到期前大约 10 秒,客户端向 /oauth2/token 发出另一个 POST 请求,这次使用以下参数:
刷新令牌:... grant_type: "refresh_token" client_id:“我的客户”并返回如下成功响应:
"access_token": "...",
"token_type": "bearer",
"expires_in": 180,
"id_token": "..."
请注意,这次没有返回刷新令牌。同样的情况又发生了四次(总共大约 14 分钟,所以两次 SSOLifetime?),而刷新令牌仍然有效,最后,在第四次请求新访问令牌时,我得到了以下正文出现 400 错误:
"error":"invalid_grant",
"error_description":"MSIS9615: The refresh token received in \u0027refresh_token\u0027 parameter has expired."
这有点道理,但是......当当前刷新令牌接近到期时间时,不应该发出新的刷新令牌吗?
Official Docs 在这件事上有些神秘:
虽然刷新令牌在用于获取新令牌时不会被撤销 访问令牌,您应该丢弃旧的刷新令牌。作为 根据 OAuth 2.0 规范:“授权服务器可能会发布一个新的 刷新令牌,在这种情况下客户端必须丢弃旧的刷新 令牌并将其替换为新的刷新令牌。授权 服务器可以在发出新的刷新后撤销旧的刷新令牌 令牌给客户端。” AD FS 在新的刷新时发出刷新令牌 令牌生命周期比之前的刷新令牌生命周期长。查看 有关 AD FS 刷新令牌生命周期的其他信息,请访问 AD FS 单点登录设置。
呃,什么?让我用伪代码写一下:
if (newRefreshTokenLifetime > previousRefreshTokenLifetime)
issueNewRefreshToken();
...但那将是总是,不是吗?
关于如何配置 AD FS 以便它在需要时也发出新的刷新令牌有任何想法吗?理想情况下,拥有refresh token rotation 会很好,但一次只做一件事......
【问题讨论】:
【参考方案1】:通常在 OAuth 中,刷新令牌的生命周期是在委派时设置的,当用户登录时,他们可能会同意在特定时间内使用某些权限。
因此,如果用户在 09:00 登录 8 小时会话,并且他们的应用在 10:00 刷新访问令牌,那么如果发布了新的刷新令牌,则它应该可以使用 7 小时。也就是说,您不能在不再次涉及用户的情况下覆盖初始委托。
正如您所说,更新的趋势是在每次访问令牌刷新时获取一个新的刷新令牌,但这只是一种保护机制,ADFS 不支持。所以我会按照以下方式进行:
将 SSO 生命周期设置为所需值,例如 8 小时,并将访问令牌生命周期设置为标准值,例如 30 分钟 以面向未来的方式编写代码,以在获得新的刷新令牌时丢弃现有的刷新令牌在本机应用程序中刷新令牌
基于 cmets,您正在尝试使用 PKCE,并希望使用旋转刷新令牌,但 ADFS 不支持后者,因此您不能。
您有一个本机应用程序,其中标准解决方案始终是将刷新令牌存储在安全操作系统存储中,仅适用于应用程序和用户。刷新令牌是否旋转无关紧要。例子:
Desktop App ios App android AppSPA
令牌和浏览器是一个完全不同的话题,因为没有地方可以安全地存储刷新令牌。由于最近的第三方 cookie 浏览器限制,让 javascript 应用程序运行的唯一方法是将刷新令牌存储在本地存储中,从安全角度来看这是灾难性的。
这个棘手问题的最佳解决方案是使用 API 驱动的解决方案,其中实用程序 API 为 SPA 发出 SameSite=strict cookie。不过,有一些活动部件可以部署到开发人员 PC 和您的管道。有关设计模式的详细信息,请参阅以下 Curity 资源。这也适用于 ADFS。
Code Docs【讨论】:
关键是 AD FS (v4.0) 似乎从未向您发送新的刷新令牌,即使当前的刷新令牌即将到期,但文档说应该... 您知道可用于 Windows Server 2019 的 AD FS 是否按预期运行?这仅仅是对 Windows Server 2016 可用的 AD FS 版本的限制吗? 2019 将表现相同 - 我的观点是你不应该依赖获取新的刷新令牌 - 因为根据 RFC6749 这不是标准的。我从来不知道任何 OAuth 系统可以在不涉及用户的情况下自动延长授权。这可能只是由于来自 Microsoft 的令人困惑的文档,其中所描述的行为不适用于代码流。这是否会导致您出现任何阻塞问题,或者仅仅是技术上的好奇? 它实际上导致了一些阻塞问题,因为我希望有一个带有 PKCE 流的授权代码也可以实现Refresh Token Rotation,既可以减少刷新令牌的生命周期,也可以保持用户在使用应用程序时进行身份验证。关于如何实现这一点的任何建议? 另外,根据 RFC6789,我不相信它不是标准的:“授权服务器可以发出一个新的刷新令牌,在这种情况下,客户端必须丢弃旧的刷新令牌并替换它使用新的刷新令牌。授权服务器可以在向客户端发出新的刷新令牌后撤销旧的刷新令牌。“根据标准,这不是强制性的,但它可以实现(这就是使刷新令牌轮换标准兼容的原因,我相信)。 根据您上次的编辑,您有点暗示刷新令牌的生命周期很长,即天/月。这对于原生应用程序来说通常是可以的,但是单页应用程序呢?我认为这是带有刷新令牌轮换的 PKCE 的主要用例。无论如何,我猜你回答了我的问题,现在无法使用 AD FS 进行配置。谢谢!以上是关于使用 AD FS 4.0 (2016) 或更高版本获取新的刷新令牌的主要内容,如果未能解决你的问题,请参考以下文章
此版本的 Android Studio 无法打开此项目,请使用 Android Studio 4.0 或更高版本重试
检查 iOS 版本是不是与 PHP 兼容,从 iOS 3.0 到 IOS 4.0 或更高版本