我有一个新的SPA,使用JWT的无状态认证模型。我经常被要求参考OAuth的认证流程,比如要求我为每个请求发送'承载令牌,而不是简单的令牌头,但我确实认为OAuth比简单的基于JWT的认证要复杂得多。主要的区别是什么,我应该让JWT认证表现得像OAuth吗?
我也在使用JWT作为我的XSRF-TOKEN来防止XSRF,但有人要求我把它们分开?我应该把它们分开吗?如果有任何帮助,我们将不胜感激,并可能为社区制定一套准则。
TL;DR 如果你有非常简单的场景,比如一个单一的客户端应用程序,一个单一的API,那么它可能不值得去使用OAuth 2.0,另一方面,很多不同的客户端(基于浏览器的,本地移动,服务器端等),那么坚持OAuth 2.0的规则可能比试图滚动自己的系统更容易管理。
正如另一个答案所说,JWT(学习JSON网络令牌)只是一种令牌格式,它定义了一种紧凑和独立的机制,用于在各方之间传输数据,因为它是数字签名的,所以可以被验证和信任。此外,JWT的编码规则也使得这些令牌在HTTP的范围内非常容易使用。
由于是自含的(实际的令牌包含了关于特定主体的信息),它们也是实现无状态认证机制的一个很好的选择(又称Look mum,没有会话!)。当走这条路时,一方必须出示的唯一被授予访问受保护资源的东西是令牌本身,有关的令牌可以被称为承载令牌。
在实践中,你正在做的事情已经可以被归类为基于不记名令牌。然而,请考虑你不是在使用OAuth 2.0相关规范所规定的承载令牌(见RFC 6750)。这将意味着,依靠 "授权 "HTTP头并使用 "承载 "认证方案。
关于使用JWT来防止CSRF,如果不知道确切的细节,很难确定这种做法的有效性,但说实话,它似乎并不正确和/或值得。以下文章(Cookies vs Tokens: The Definitive Guide)可能对这个问题有帮助,特别是XSS和XSRF保护部分。
最后一个建议,即使你不需要完全采用OAuth 2.0,我也强烈建议在 "授权 "头中传递访问令牌,而不是使用自定义头**。如果他们真的是不记名令牌,请遵循RFC 6750的规则,如果不是,你总是可以创建一个自定义的认证方案,并仍然使用该头文件。
授权头被HTTP代理和服务器识别并特别处理。因此,使用这种头向资源服务器发送访问令牌,可以减少泄漏或意外存储一般认证请求的可能性,特别是授权头。
(来源:RFC 6819,第5.4.1节)
OAuth 2.0定义了一个协议,即规定了令牌的传输方式,JWT定义了一个令牌格式。
OAuth 2.0和"JWT认证"在涉及到客户向资源服务器提交令牌的(第二)阶段时有相似的外观:令牌在头文件中传递。
但是"JWT认证"并不是一个标准,也没有规定客户首先如何获得令牌(第一阶段)。这就是OAuth的复杂之处:它还定义了各种方法,使客户可以从被称为授权服务器的东西那里获得访问令牌。
因此,真正的区别是,JWT只是一种令牌格式,OAuth 2.0是一种协议(可能*使用JWT作为令牌格式)。
首先,我们要区分JWT和OAuth。基本上,JWT是一种令牌格式。OAuth是一个授权协议,可以使用JWT作为令牌。OAuth使用服务器端和客户端的存储。如果你想做真正的注销,你必须使用OAuth2。使用JWT令牌的认证实际上不能注销。因为你没有一个可以跟踪令牌的认证服务器。如果你想为第三方客户提供一个API,你也必须使用OAuth2。OAuth2是非常灵活的。JWT的实现非常容易,而且不需要很长时间。如果你的应用程序需要这种灵活性,你应该选择OAuth2。但如果你不需要这种使用场景,实现OAuth2就是浪费时间。
XSRF令牌总是在每个响应头中被发送到客户端。是否在JWT令牌中发送CSRF令牌并不重要,因为CSRF令牌本身是安全的。因此,在JWT中发送CSRF令牌是不必要的。