当前位置: 首页 > 知识库问答 >
问题:

使用AD FS 4.0(2016)或更高版本获取新刷新令牌

岳俊晖
2023-03-14

我将AD FS 2016配置为支持通过使用PKCE授权代码授予的OAuth2/OpenID Connect对“本机应用程序”进行身份验证。我创建了一个依赖方,并通过设置以下内容配置(用于测试目的)令牌生命周期:

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/tokenendpoint发出POST请求,传递以下参数

    < li>client_id: "MyClient" < li >代码:... < li >重定向uri:... < li >代码验证器:... < li >授权类型:"授权代码"

我得到以下有效回复:

{
  "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请求,这次使用以下参数:

    < li >刷新令牌:... < li >授权类型:"刷新令牌" < li>client_id: "MyClient"

并返回以下成功响应:

{
  "access_token": "...",
  "token_type": "bearer",
  "expires_in": 180,
  "id_token": "..."
}

请注意,这一次没有返回刷新令牌。同样的情况还会发生四次(总共大约14分钟,那么是SSO寿命的两倍?)当刷新令牌仍然有效时,最后,在第四次请求新的访问令牌时,我得到了一个400错误,其正文如下:

{
  "error":"invalid_grant",
  "error_description":"MSIS9615: The refresh token received in \u0027refresh_token\u0027 parameter has expired."
}

这有点道理,但是...当当前刷新令牌接近到期时间时,不应该颁发新的刷新令牌吗?

官方文件在这个问题上有些含糊不清:

虽然刷新令牌在用于获取新的访问令牌时不会被撤销,但您应该丢弃旧的刷新令牌。根据 OAuth 2.0规范 表示:“授权服务器可能会发布新的刷新令牌,在这种情况下,客户端必须丢弃旧的刷新令牌并将其替换为新刷新令牌。授权服务器可能在向客户端发布新刷新令牌后撤销旧刷新令牌。”当新刷新令牌的生存期长于以前的刷新令牌生存期时,AD FS会发布刷新令牌。要查看有关AD FS刷新令牌寿命的其他信息,请访问AD FS单一登录设置。

呃,什么?让我用伪代码来写:

if (newRefreshTokenLifetime > previousRefreshTokenLifetime) {
  issueNewRefreshToken();
}

...但那总是这样,不是吗?

关于如何配置AD FS以便它在需要时也发布新的刷新令牌,您有什么想法吗?理想情况下,有刷新令牌循环会更好,但一次只能做一件事...

共有1个答案

邹玄裳
2023-03-14

通常在 OAuth 中,刷新令牌的生存期是在委派时(用户登录时)设置的,此时他们可能会同意在特定时间内使用某些权限。

因此,如果用户在09:00登录一个8小时的会话,并且他们的应用程序在10:00刷新访问令牌,如果发布了新的刷新令牌,那么它应该可以使用7小时。也就是说,在不再次涉及用户的情况下,不能覆盖初始委托。

正如您所说,最新的趋势是在每次访问令牌刷新时获得一个新的刷新令牌,但这只是一种保护机制,ADFS不支持这一点。因此,我将继续如下:

  • 将SSO生存期设置为所需值,例如8小时,并将访问令牌生存期设置成标准值,例如30分钟
  • 以面向未来的方式编写代码,如果获得新的刷新令牌,则丢弃现有的刷新令牌

刷新本机应用中的令牌

根据评论,你正在尝试使用PKCE,并希望使用旋转刷新令牌,但ADFS不支持后者,所以你不能。

您有一个本机应用程序,其中的标准解决方案一直是将刷新令牌存储在仅供应用程序和用户使用的安全操作系统存储中。刷新令牌是否旋转并不重要。示例:

  • 桌面应用程序
  • iOS应用程序
  • Android应用程序

温泉

令牌和浏览器是一个完全不同的主题,因为没有地方可以安全地存储刷新令牌。由于最近的第三方cookie浏览器限制,使Javascript应用程序工作的唯一方法是将刷新令牌存储在本地存储中,从安全角度来看,这是灾难性的。

这个棘手问题的最佳解决方案是使用API驱动的解决方案,其中实用程序API为SPA发出SameSite=严格cookie。不过,有一些移动部件可以部署到开发人员PC和您的管道中。有关设计模式的详细信息,请参阅下面的安全资源。这也适用于ADFS。

  • 代码
  • 文档
 类似资料:
  • 我编写了一个控制台ASP.NET应用程序来获取AccessTokens。我有clientId,我的应用程序的客户端秘密,我做了以下操作: var authContext=新的AuthenticationContext(“https://login.windows.net/common/oauth2/authorize”);var acquireTask=authContext.AcquireTok

  • 我正在使用pullToRefresh库: 但是如果android版本大于4.0,列表无法移动。 LogCat显示模拟器警告,但它们不相关。 如何解决移动列表的问题?

  • 我有一个SPA,用户在ADFS中进行身份验证,应用程序获得访问令牌。我正在尝试使用JS代码来模拟ADAL JS的功能,其中使用一个隐藏的iframe向ADFS请求获取新令牌。 这是 iframe 的 'src' 值: https://../adfs/oauth2/authorize?客户端id=... ADFS配置有两个域:AD和ADLDS(LDAP)。因此,我不确定需要传递哪些值domain_h

  • 目前访问类型处于联机状态。当我需要访问驱动器上的文件/文件夹时,我将浏览器重定向到Google URL并获得访问代码: 一切运转良好!但我只需要第一次重定向。 当我谷歌时,在google Drive API文档中,我发现我可以通过浏览器重定向获得刷新令牌,并将其保存在数据库中。(换句话说,我可以使用脱机访问)。 而且每次当我需要从google drive读取数据时,我使用刷新令牌获得访问令牌,而无

  • 我的问题是如何使用OAuth2.0从刷新令牌中获取访问令牌。我还没有找到任何从刷新令牌中获取访问令牌的例子。 我参考了[Google+API参考],但他们使用HTTP方法提到了它。2请用C#提供一些使用Google+API提供的方法的例子。

  • 我正在编写一个应用程序,调用来自Flutter的google fit rest api。 我需要使用(https://pub.dev/packages/google_sign_in)与谷歌签名。我可以毫无问题地获得一个令牌(见是否有人设法从谷歌登录(Flutter)获得id令牌),但如何获得一个新的令牌时,它是过期的? 我不想要求用户每小时登录并获得一个新的令牌