如何将OAuth与单页面应用程序集成?

47

当使用OAuth(2)时,我需要在应用程序中设置一个重定向端点,以便OAuth提供服务可以在我完成身份验证后重定向到该端点。

在单页面应用程序中如何处理此问题?当然,在这里重定向到OAuth提供的服务并不好,并且甚至可能无法返回重定向。

我知道OAuth还支持基于用户名/密码的令牌生成。这可以通过AJAX调用完美地解决,但需要我的单页面应用程序请求用户名和密码。

你通常如何处理这个问题?

3个回答

51

大多数情况下,即使对于SPA,重定向也是可以的,因为用户不喜欢将其X服务凭据放在除X以外的任何其他网站上。另一种选择是使用小弹出窗口,您可以查看Discourse所做的内容。我认为重定向比弹出窗口更好。

Google有些提供商支持所有者资源流程,这就是您描述的发送用户名和密码,但这样做并不好。 我看到的问题如下:

  1. 要求用户在您的网站上使用Google凭据可能会成为某些用户的禁忌。
  2. 所有者资源流程还需要客户端秘钥,这是您绝不能放置在客户端JavaScript中的内容。 如果您从服务器端应用程序实例化所有者资源流程,并且您的应用程序与用户不在同一地理区域,则用户将收到警告“嘿,有人正在尝试使用您的凭据从印度访问”。

OAuth描述了称为隐式流程的客户端流程。使用此流程,您不需要在服务器端进行任何交互,也不需要客户端秘钥。 OAuth提供程序将带有“#access_token=xx”的重定向到您的应用程序。它被称为隐式是因为您不需要根据访问令牌交换授权代码,您直接获得访问令牌。

Google实现了隐式流程,请查看:如何在客户端应用程序中使用OAuth2

如果您想使用隐式流程来与一些不支持它的提供商(例如Github)进行交互,则可以使用身份验证代理,例如Auth0

免责声明: 我为Auth0工作。


21

何塞·F·罗马尼洛所的是正确的。然而,由于您的问题比较宽泛,因此我认为任何提供的结论都只是一般性的。

应用程序状态

例如,如果不知道您在何时让用户登录时应用程序状态有多么复杂,没有人能确切地知道是否使用重定向实际上可行。请考虑您可能愿意让用户在工作流/应用程序使用的最后阶段登录,在这个阶段,您的应用程序保存了您真正不想为没有充分理由序列化和保存的状态。更不用说编写代码来重建它了。

注意:您会在网上看到很多忽略这一点的建议。这是因为许多人将他们应用程序的大部分状态存储在服务器端的会话存储中,而很少存储在他们(薄)客户端上。有时候是出于错误,有时候确实是有道理的——如果您选择忽略它,请确保它对您有意义。如果您正在开发一个厚客户端,通常不需要考虑。

弹出对话框

我意识到弹出窗口在网络上因所有不良用途而声名狼藉,但人们必须考虑其良好应用。在这种情况下,它们与其他类型系统中的trusted dialogs(比如Windows UAC, fd.o polkit等)完全具有相同的作用。这些界面都使自己可识别,并利用底层平台的特性确保它们无法被欺骗并且输入或显示不能被非特权应用程序拦截。确切的类比是浏览器的chrome和特别是证书锁可以防止欺骗,并且单一来源策略防止应用程序访问弹出窗口的DOM。对话框(弹出窗口)和应用程序之间的交互使用cross-document messagingother techniques

至少在浏览器标准化权限授权之前,这可能是最优的方式,如果他们真的能做到的话。即使如此,某些资源提供者的授权流程可能不符合标准化实践,因此像今天看到的灵活的自定义对话框可能仍然是必要的。

同窗口过渡

考虑到这一点,弹出窗口的美学是主观的。将来,浏览器可能会提供API,允许在不卸载现有文档的情况下在现有窗口上加载文档,然后允许新文档卸载并恢复先前的文档。无论“隐藏”的应用程序是否继续运行或被冻结(类似于虚拟化技术如何冻结进程)都是另一个争议。这将允许与弹出窗口相同的过程。据我所知,目前没有这样的提案。 注意:您可以通过某种方式使所有应用程序状态易于序列化,并具有存储和从本地存储(或远程服务器)还原它的过程来模拟此过程。然后可以使用老式重定向。但正如一开始所暗示的那样,这可能对应用程序代码非常侵入。
选项卡
当然,另一个选择是打开一个新选项卡,像处理弹出窗口一样与其通信,然后以同样的方式关闭它。
关于从非特权应用程序获取用户凭据
当然,只有用户信任你不会将凭据发送到你的服务器(或任何他们不想要的地方),才能使其正常工作。如果你开源代码并进行确定性构建/最小化,则理论上用户可以审核或让某人审核代码,然后自动验证你未篡改运行时版本——从而获得他们的信任。据我所知,在Web上还没有这样的工具。 话虽如此,有时候你想要使用OAuth与一个在你控制/权威/品牌下的身份提供者配合使用。在这种情况下,整个讨论都是无意义的——用户已经信任你了。

结论

最终,这取决于(1)你的客户端有多厚,以及(2)你希望UX是什么样子。

1
这在我的前一个答案中添加了很多缺失的信息,干得好!根据我的经验,我想再补充一些内容:如果您计划让应用程序在移动设备和平板电脑上运行,弹出窗口是一个不好的选择,因为从技术上讲,它会引入复杂性,因为父标签“冻结”,所以您无法观看子标签或监听事件,这会影响用户体验。因此,如果您计划支持移动设备,则应避免使用弹出窗口。 - José F. Romaniello
@JoséF.Romaniello 很好的观点!你知道这个问题有多普遍吗?我似乎找不到关于 window.open 的兼容性列表,尽管我相信你的行为肯定是不一致的。不确定 完整的 x-doc 消息支持是否意味着良好的行为;如果是这样,也许它正在变得更好。模态对话框也可以使其工作(大多数网站外的授权系统实际上使用模态对话框,但出于不同的原因),但我也找不到任何兼容性列表。它们可能还需要特殊的 UA 权限。 - tne

2

OAuth2有4种流程,也称为授权类型,每种流程都有特定的目的:

  • 授权码(你提到的那个,需要重定向)
  • 隐式
  • 客户端凭据
  • 资源所有者密码凭据

简短的答案是:使用隐式流程。

为什么?选择流程或授权类型取决于您的代码中是否有任何部分可以保持私密,因此能够存储秘密密钥。如果有,您可以选择最安全的OAuth2流程-授权码,否则您将不得不在较不安全的OAuth2流程上做出妥协。例如,对于单页应用程序(SPA),将使用隐式流程。

客户端凭据流程仅在Web服务和用户是同一实体时有效,即Web服务仅服务于该特定用户,而资源所有者密码凭据流程是最不安全的,只有作为最后手段时用户才需要向服务提供其社交登录凭据。

要完全了解推荐的隐式流程和授权码流程(你提到的需要重定向的流程)之间的区别,请查看以下流程的对比:

Comparing 'Implicit' and 'Authorization Code' flow side-by-side

此图表来自:https://blog.oauth.io/introduction-oauth2-flow-diagrams/


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