02. 全网最权威!!!一文带你深入浅出理解:OAuth 2 和 OIDC 究竟是什么各自又究竟在解决什么问题

铭记历史才能展望未来,在前一小节我们追根溯源,讲述了身份认证和授权的发展历史。在小节的末尾我用一张图说明了它们各自解决的问题,即OAuth 2是用于授权访问的框架,而OIDC和SAML 2则解决了联合身份认证的问题,那么究竟什么委托授权和联合身份认证呢?为了搞清楚这个问题,我们先了解基本两个概念——认证和授权。
image

认证 vs 授权

认证(Authentication)

认证是验证一个人(或系统)是否真的是他们自己所说的主体的过程,认证的目的是为了认出用户(或系统)是谁 。
一般来说认证的主体都是人,但是也有可能是系统。在OAuth的世界里,不管是在哪种授权类型,客户端必须提供自己的身份凭据(客户端ID或客户端密钥),授权服务器根据客户端提供的凭证信息来认证客户端,此时认证的主体不再是“人”,而是系统。
我们举个生活中的例子,我们将网络中的系统想象成一个北京的大四合院,里面混居着很多住户,四合院可以用电子门禁卡或者钥匙打开,只有持有四合院门禁卡或大门钥匙的住户才能打开院门进入院子,认证的过程就是开门的过程。

对用户进行身份验证的方法称为身份验证要素(authentication factor),比如这里的大门钥匙或者电子门禁卡。在现实世界里的身份验证要素是很丰富的,比如密码、钥匙甚至生物特征要素(比如指纹或人脸等)。我们称认证过程中只使用一个身份验证要素认证为“单因素认证”,有多于一个身份验证要素的认证为“多因素认证”。在后文我们的授权服务器认证实现将使用双因素认证。

授权(Authorization )

授权指的是一旦你经过身份认证,你可以做什么。
我们继续使用上面大四合院的例子,你进入院门之后,可以做或者不能做哪些事情就是授权管辖的范围了。比如你可以去公共厕所,你可以在大宅院里晒太阳,但是你只能进入你自己的屋子,不能进入其他人的屋子。

联合身份认证 vs 访问授权

那么究竟什么是联合身份认证和访问授权呢?

你曾经也许在很多网站维护或共享过个人资料,例如你在掘金、在人人网、在QQ等,你都注册和分享了你的个人信息,例如邮箱和电话号码等。你对外分享和暴露的个人信息越多,你就越担心自己的信息安全问题。更不用说某一天你更改了自己的电话号码,你需要分散地更新这些信息。而通过联合身份认证,你只需要在某个地方(在OIDC中我们称这样的角色为OpenID Provider,即提供身份认证的服务方)分享和维护的个人信息,其他的网站都与OpenID Provider通信来获取你的个人信息。这就是联合身份认证。

如下图所示,小张是掘金的深度用户,他想在掘金上分享一些技术文章。那么第一步他需要登录掘金。但是小张想跳过繁琐的注册过程,因为他不想记住那么多的账号密码。幸运的是,掘金提供了微信登录的方式,这样他直接使用微信登录了掘金。这就是一个联合身份认证的案例。联合身份认证指的是一个应用程序通过另外一个应用程序来认证当前用户的主体。通过联合身份认证,微信将用户的身份信息(比如昵称、邮箱、电话等)以某种安全的方式“悄悄”分享给了掘金。
image

那么什么又是访问授权呢?如上图所示,小明是抖音的视频创作者,他发现最近他的粉丝数量减少了很多,因此他想借助一款叫做“抖音助手”的应用程序帮他做一些数据分析以找出粉丝数锐减的原因。因此第一步他访问了抖音助手,但是巧妇难为无米之炊,抖音助手必须从抖音获得小张的音视频数据它才能进行接下来的工作。为了获得小明的音视频数据,一种最直接的方式小明可以将自己的抖音身份认证信息(比如用户名和密码)分享给抖音助手,抖音助手扮演小明的角色,“假装自己是小明”登录了抖音获得小明的音视频数据(比如粉丝数、点赞数、评论数等数据),这是OAuth诞生之前的一般做法,我们在上一小节讨论了这种方式的漏洞和缺陷,它是坚决不可取的(实际上它是OAuth 2规约的一种授权模式,即密码模式,这种模式在OAuth 2.1中已经被彻底废弃)。访问授权指的是服务或应用程序代表用户访问用户托管在另外一个服务或应用程序的资源的能力。例如抖音助手代表用户访问终端用户托管在抖音的数据。

OAuth 2 vs OIDC

OAuth 2

OAuth 2的诞生就是为了解决上面的场景中抖音助手代表小明访问小明的抖音数据的问题。有了OAuth 2,小明无需再向抖音助手分享其抖音认证信息(比如用户名和密码)。抖音助手最终获得了一把代表小明访问小明抖音数据的钥匙——访问令牌(Access Token),这把钥匙是有时限的,它绑定了对单个受保护资源或一组受保护资源的授权,这些授权信息也是经过小明确认后的结果。例如上面最初抖音助手除了获得小明的抖音视频数据外还想获得小明的粉丝数据,但是小明在授权确认阶段驳斥了抖音助手获得其粉丝数据的权限。在钥匙的有效期内,抖音助手可以重复获取小明的抖音数据,而一旦访问令牌遭到破坏——例如一个小偷(对应的网络的世界里我们往往称他们是“黑帽子”)他偷偷复制了这把钥匙,那么这时钥匙已经不再安全,抖音助手或者小明都可以销毁这把钥匙,对应OAuth 2里我们称为撤销令牌。

OAuth 2.0是关于授权而不是身份验证的。使用OAuth 2.0,客户端不知道终端用户是谁。它只需获取一个访问令牌,即可代表用户访问资源。

我们细化一下这个场景里OAuth 2的工作过程,下图展示了OAuth 2的工作过程,这里忽略了很多的细节,但是很快在OAuth 2的关卡里你会了解到这些细节的所有内容。
image

  1. 小明访问抖音助手,想让抖音助手帮他做一些数据分析的工作,因为最近他的粉丝数有所下跌。
  2. 巧妇难为无米之炊,为了获得小明的抖音数据,抖音助手将小明引导到抖音获取小明的授权。
  3. 抖音向小明展示授权页面,询问小明是否分享这些数据给抖音助手。
  4. 小明做出了决策——可以分享音视频数据,但是粉丝画像数据是敏感的数据,他拒绝了抖音助手获取这些数据的权限。
  5. 抖音向抖音助手颁发了一个有时限的、绑定了授权信息(获取小明的视频基础数据以及点赞数、评论数、分享数等权限)的钥匙。
  6. 抖音助手使用这把钥匙访问小明的资源。

OAuth 2定义了四种角色——资源所有者(resource owner)、资源服务器(resource server)、客户端(client)以及授权服务器(authorization server)。其中上图中的小明就是资源所有者角色,抖音助手就是客户端角色,我们在第一关的第(4)小节会详细描述这四种角色的职责。

滴水不成海,独木难成林。在电影的世界里,各个角色互相交流和配合推动整个电影故事线的发展,最终向观众完整地呈现一个故事。同样的在OAuth 2的世界里,OAuth 2需要描述四种角色如何相互配合和交互完成最终的目的——客户端代表资源拥有者访问资源拥有者托管在资源服务器上的资源。为此,OAuth 2定义了四种授权方式,授权方式描述了客户端如何从资源所有者处获得授权许可,以代表其访问托管在资源服务上的资源。

  1. 授权码模式:
    授权码模式是最重要也是最严谨的授权模式。这种授权方式使用了一个重要的中间介质——授权码,来保证客户端最终用来向资源服务器交换资源的访问令牌不被暴露在操作代理(终端用户的浏览器)上,同时它安全地保存了客户端ID和客户端密钥以及访问令牌。一般的这种授权方式适用于服务端应用程序。值得注意的是,授权码同样也有失窃的风险,为了防范授权码失窃攻击,RFC 7636定义了一种PKCE来增强授权码安全。PKCE最初是为隐式授权模式设计的,但是在OAuth 2.0最佳安全实践里推荐对于授权码模式也应该使用PKCE来增强授权码安全。我们在第二关的第(12)小节里会讨论如何在授权码模式中使用PKCE。
  2. 客户端模式:
    可以说客户端模式是四种授权模式中最简单的授权模式。在这种模式下,少了角色终端用户的参与。客户端直接与授权服务器对话获取访问令牌,然后使用获得访问令牌与资源服务器对话获取资源。我们在第二关的第(12)小节会讨论这种模式。
  3. 密码模式:
    密码模式与我们在第(1)小节中讨论的蛮荒时代,没有OAuth的世界部分讨论的工作模式很像。在这种模式下需要终端用户与客户端应用程序共享其用户认证信息(用户名和密码)。我们已经讨论了这种工作模式的风险和弊端,事实上OAuth 2.1已经完全废弃了这种模式,但是作为补充,我们还是在第一关的(13)小节讨论这种模式。
  4. 隐式授权模式:
    我们称这种模式是简化模式的原因是相对于授权码模式,这种模式简化了客户端使用中间介质——授权码向授权服务器申请访问令牌的过程。这种模式适用于无法安全存储访问令牌以及客户端ID和客户端密钥的客户端,例如在纯粹在浏览器中运行的JavaScript程序。这种模式在过往的实践中已经被证明是不安全的,因此OAuth 2.1也已经完全废弃了这种模式,但是作为补充,我们还是在第一关的(13)小节讨论这种模式。同时OAuth 2.0安全实践里要求这种模式必须使用PKCE技术,因此在第一关的(14)小节里我们会构建一个基于React构建的单页面应用程序演示授权码模式与PKCE联合工作的过程。

OIDC

在由IETF的制定的OAuth标准RFC 6749(http://tools.ietf.org/html/rfc6749)文档中,它强调了OAuth 2是一个授权框架(The OAuth 2.0 Authorization Framework),它解决了代理授权的问题,
但是它并没有解决身份认证的问题,身份认证会告诉当前的应用当前的用户是谁以及是否在使用当前的应用,身份认证协议还会告诉你一些其他的用戶身份属性或身份断言,比如唯一标识符、邮箱地址、用户地址、性别或者用户是否超过18岁等信息。我们回顾一下上面抖音助手的案例,抖音助手最终获得了代表用户访问用户抖音数据的钥匙——访问令牌,这个访问令牌对客户端是不透明的,它只对授权服务器或资源服务器有意义,对客户端来说它就是一个无意义的字符串。抖音自始至终都没有告诉抖音助手当前用户是谁。使用微信登录掘金是一个认证的例子,在联合认证的最后,微信通过某种方式告诉了掘金当前用户是谁。

OIDC就是用来解决联合身份认证的问题。OIDC是构建在OAuth 2.0 框架之上的一个简单身份验证层,它以标准化的格式向应用程序提供关于已认证用户的身份信息。相对于OAuth 2 ,OIDC是在客户端级别的,OAuth 2使用访问令牌访问资源服务器开放的各种API,而OIDC的目的只有一个 —— 告诉客户端(在OIDC里客户端被称为是Relying Party,即认证服务的依赖方,简称RP)当前访问客户端的终端用户是谁。在OIDC的最后RP获得了一个ID令牌(或可选的一个访问令牌),这个ID令牌是一个JWT令牌,它“裹挟”了终端用户的身份信息。相对于OAuth 2的访问令牌,这个令牌对客户端是一个有意义的令牌,它会直接告诉RP当前登录的终端用户身份信息或身份断言,客户端不再需要使用该令牌去调用资源API。因此这也是OIDC只设计了三种角色的原因——即End User(终端用户,简称EU)、Relying Party(认证服务的依赖方,简称RP)和OpenID Provider(提供身份认证的服务方,简称OP),它缺失了资源服务器的角色。你很快在OIDC的部分看到这些内容细节。

OIDC还提供了单点登录的功能。每当你登录RP时,都会被重定向到OP。你在OP的应用程序的域下登录并且批准了来自RP的身份属性请求,之后OP将你重定向回RP并且返回了你的身份信息。一旦你在OP登录,其他RP再重定向回OP,此时只要OP的域下有有效的会话信息,OP不再要求用户重复认证。这给用户提供了单点登录的体验。

我们细化一下小张使用微信登录掘金的场景。下图展示了OIDC的工作过程,这里忽略了很多的细节,但是很快在OIDC的部分你会了解到这些细节的所有内容。同时我们只讨论标准的OIDC实现,微信的实现会有差异,但是相信标准化的力量。
image

  1. 小张想跳过繁琐的注册过程,选择使用微信登录掘金社区。
  2. 掘金将终端用户重定向到OP进行身份认证。
  3. 微信要求终端用户进行登录,用户扫码登录成功后微信将向用户展示掘金正在请求的用户属性。
  4. 小张同意了掘金的授权请求。
  5. OP将终端用户重定向回稀土掘金,此时用户可能会直接返回一个包含用户信息的自包含令牌(ID令牌)和一个可选的访问令牌(是否返回访问令牌取决于身份认证请求中的response_type参数值)。掘金可以直接解析ID令牌获取用户的属性信息。我们将在OIDC的部分讨论这些细节的详细内容。
  6. 如果有访问令牌,掘金可以使用该访问令牌与OP的一个特殊端点——userinfo端点对话,请求获取用户的属性信息。我们将在OIDC的部分展开讨论访问令牌和userinfo端点存在的必要以及它们的各个细节。

类似于OAuth 2,OIDC也定义了三种OIDC的三种身份认证流(授权码流、简化流以及混合流),用来传递用户的身份信息。你在OIDC的部分会看到关于这些身份认证流的详细讨论。

参考规范

在本文的最后,我向你列出关于OAuth和OIDC的重要参考规范。这些规范是最权威和最准确的内容表述,如果你想深入了解某部分内容,你可以直接阅读对应的内容。

  1. OAuth 2规范(The OAuth 2 Authorization Framework):
  1. Bearer令牌的使用(The OAuth 2 Authorization Framework: Bearer Token Usage):
  1. OAuth 2令牌撤销规范(OAuth 2.0 Token Revocation)
  1. OAuth 2令牌自省端点(OAuth 2.0 Token Introspection)
  1. PKCE技术(Proof Key for Code Exchange by OAuth Public Clients)
  1. 在无浏览器或或输入受限设备中使用OAuth(OAuth 2.0 Device Authorization Grant)
  1. 动态客户端注册技术( OAuth 2.0 Dynamic Client Registration Protocol)
  1. 授权服务器元信息端点描述(OAuth 2.0 Authorization Server Metadata)
  1. OAuth 2.1规范(The OAuth 2.1 Authorization Frameworkdraft-ietf-oauth-v2-1-07)
  1. OIDC规范
  1. 其他规范:这并不是OAuth和OIDC的所有规范,其他规范我们将在讨论对应内容对应的小节展开介绍

总结

这一小节总览全局向你介绍了OAuth 2和OIDC技术,我将在后面的小节与你讨论关于OAuth 2和OIDC的绝大多数细节。你现在在第零关的最后一个部分,下一节开始我们将正式开始探索OAuth的世界线。万丈高楼平地起,请保持耐心。再一次,这是一门从零开始的OAuth 2和OIDC的实战课,如果你已经对某一部分的内容较为熟悉,你可以跳过这一关卡直接探索下一关卡或你感兴趣的关卡!
image

posted @ 2023-05-07 11:12  小米粥|  阅读(114)  评论(0)    收藏  举报