处理OAuth2隐式授权中过期的访问令牌

30
OAuth2规范声明,在使用隐式授权时,授权服务器不得发出刷新令牌。在我们的用例中,我们使用OAuth2保护RESTful API,并使用单页JavaScript应用程序作为此API的客户端。由于在访问令牌过期后重定向到授权服务器将非常困难,因此我们正在寻找更好的方法来获取新的有效令牌。我可以考虑两种不同的方法,并想知道哪一种可能更好:
  1. 使用隐藏的iframe重新请求有效的访问令牌。为此,需要包含一个参数“prompt = none”,它告诉OAuth提供程序既不要挑战身份验证,也不要显示授权页面。如果用户已通过身份验证并已授权应用程序,则服务器将在url的#参数中发送回访问令牌。如果未满足先前的任何条件,则会使用错误重定向,例如#error = authentication%20lost。通过这种行为,我们可以使用短期的访问令牌,也可以使用隐式流。
  2. 我们可以使用其他范围(例如离线),告诉服务器发放刷新令牌。即使原始规范表示隐式流不发出刷新令牌(如果客户端只是首次授权使用OAuth),您可以自由定义适用于特定应用程序的自己的范围。您应该考虑仅允许来自知名客户端的此范围。
这两种方法与OpenID Connect非常相似。不幸的是,目前没有多少OpenID Connect实现。因此,第一步是扩展OAuth2服务器,直到OIC更受欢迎。
因此,哪种方法应该优先考虑? 注意:令牌终结点需要客户端身份验证,这仅对像服务器端应用程序这样的机密客户端可能。对于第二种方法,我们只能让RESTful API在我们的情况下作为资源提供者刷新令牌并将其发送回客户端。我认为这将是安全风险。因此,我们可能只有一个有效的方法。

我正在寻找完全相同的东西。我可以刷新整个页面,但显然这有点愚蠢。 - Larry Anderson
如果您选择方案1,如何防止窗口被弹出拦截器屏蔽? - Lev
2个回答

3

我目前正在尝试实现完全相同的事情。

我实际上已经采用了隐藏的iframe方法,然后意识到你必须非常小心处理iframes。如果您不指定X-Frame-Options,任何恶意网站都可以包含您的iframe并轻松获取访问令牌。

根据规范,刷新令牌的最佳方法应该是密码授权。(我希望我的用户使用他们的Facebook帐户登录,而隐式流程更容易开发此功能。但我还没有完全弄清楚如何使用密码授权来实现这一点)

第二种方法也出现在我的脑海中,对我来说似乎比第一种方法更安全,因为您通常可以信任https浏览器存储来保持您的令牌秘密。

编辑

我意识到,即使使用X-Frame-Options,大多数浏览器也无法防止重定向,因为此标头附加在响应正文上,并且重定向的URL将被公开,因此访问令牌会暴露。

更新看起来,当从不同域中的父页面访问时,哈希片段受浏览器保护。因此,我认为#access_token是安全的。我的错。只是作为提醒,回调页面必须自己存储访问令牌,而不能像window.parent.storeAccessToken(hash);这样将其委托给父页面,这显然是一件愚蠢的事情。


密码授权不是一个选项,因为它需要用户登录两次(例如在您的Facebook和Javascript应用程序中)。对于第二种方法,您需要存储客户端凭据。但是,您的客户端如何获取它们?当然,您可以将它们存储在浏览器存储中。但是它们也会包含在您的Javascript文件中。所以每个人都可以从那里读取它们。我们决定实现隐藏的iframe方法。但是+x-frame-options值得一试。 - Christian Metzler
即使使用了x-frame-options,它似乎也无法防止重定向。隐式流程的重定向(浏览器不会阻止)包含作为哈希附加的访问令牌,很容易被暴露,即使iframe被阻止,我也可以从外部使用jquery获取访问令牌。因此,只要用户已登录,攻击者就可以通过让用户访问某些网页来获得新的访问令牌。我想批准页面应该防止将令牌泄漏到iframes中。 - beku8
到目前为止有任何解决方案吗? - Carlos Alberto

1

来自OAuth0网站:

如果您需要在没有登录页面的情况下对用户进行身份验证(例如,当用户已通过SSO场景登录)或获取新的access_token(从而模拟刷新过期令牌),则可以使用无声身份验证。

至于无声身份验证:

但是,从UX角度考虑,将用户重定向离开您的应用程序通常被认为是具有破坏性的,应该避免。 无声身份验证使您能够执行身份验证流程,其中Auth0仅回复重定向,而不是登录页面。

这将允许您使用SSO令牌重新登录用户,而无需再次提示他输入凭据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接