OAuth 2.0

OAuth 2.0

现如今,微信和支付宝以一种近乎病毒式的发展速度蔓延到了互联网的每一个角落,你几乎可以在所有主流应用上面看到以微信,或者以支付宝登录的字样,这种方式就是 OAuth 授权方式,让第三方应用不会触及到用户的帐号信息(如用户名与密码),即第三方应用无需使用用户的用户名与密码就可以申请获得该用户资源的授权。

简介


OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 OAuth 的授权不会使第三方触及到用户的号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,OAuth 是 Open Authorization 的简写。

OAuth 的核心思想就是引入了一个授权层,用来分离两种不同的角色:客户端资源所有者。资源所有者同意以后,资源服务器可以向客户端颁发令牌。客户端通过令牌,去请求数据,过程如下:

颁发模式


OAuth 2.0 RFC-6749 中规定了这几种模式颁发令牌:


  • 授权码

授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌,这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏,对于 SPA (Single Page Application)应用,则还有更安全的 PKCE 模式

Authorization Code Flow

Authorization Code Flow With PKCE

  • 我们以 Vercel 认证 Github 登录为例,来说一下这个模式的流程:
* ***A***. Vercel 在登录页有可以支持 Github 登录的选项,用户选择以 Github 登录 Vercel
* ***B***. 开始授权:
    * ***1*** -> 重定向到 Github 授权页面
    * ***2*** -> 用户点击允许 Vercel 访问我的个人数据
    * ***3*** -> 授权通过,返回授权码
* ***C***. 拿到授权码后,Github 认证服务器将用户导向 Vercel 事先指定的**重定向URL**(Redirection URL),同时附带上授权码
* ***D***. Vercel 收到授权码,附上之前的重定向URL,向认证服务器申请令牌,这一步在 Github 后台完成,对于用户来说是无感知的
* ***E***. 认证服务器核对了授权码和重定向URL没问题,然后给 Vercel 颁发令牌(Access Token)和更新令牌(Refresh Token)
  • PKCE 模式
* PKCE 增强的授权码流引入了一个由调用应用程序(SPA)创建的密钥,该密钥可由授权服务器验证。 这个密钥被称为 Code Verifier(代码验证器)。此外,调用应用程序为 Code Verifier 创建一个转换值,称为 Code Challenge ,并通过 HTTPS 发送该值(Code Challenge)去检索 Authorization Code。使用这种方法,恶意攻击者只能拦截到 Authorization Code,因为恶意攻击者没有 Code Verifier 因此无法从认证服务器获取 token。
Authorization Code 只能使用一次,并且是有时间限制的,RFC-6749 建议设置的时间为10分钟

  • 隐含式

有些 Web 应用是纯前端应用也就是前端渲染,通过 API 数据驱动。这时就不能用授权码的方式了,必须将令牌储存在前端。RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)”隐藏式”(implicit),也可以称之为授权码的简化模式,

  • 我们还是以 Vercel 认证 Github 登录为例,来说一下这个模式的流程:
* ***A***. Vercel 在登录页有可以支持 Github 登录的选项,用户选择以 Github 登录 Vercel
* ***B***. 开始授权:
    * ***1*** -> 重定向到 Github 授权页面
    * ***2*** -> 用户点击允许 Vercel 访问我的个人数据
* ***3***. 授权通过,Github 认证服务器将用户导向 Vercel 事先指定的**重定向URL**(Redirection URL),同时附带上授权码
* ***4***. Github 收到重定向响应后,向 Vercel 服务器表示想提取 URL 中的 Access Token
* ***5***. Vercel 服务器返回带有解析脚本的页面,用于解析重定向 URL Fragment 中的 Access Token
* ***6***. User-Agent 使用解析脚本,获取 Access Token
* ***7***. User-Agent 将 Access Token 转交给 Vercel
此模式不生成 Refresh Token

  • 密码式

RFC 6749 规定也允许用户把用户名和密码直接告诉该应用。该应用就使用你的账户信息申请令牌。

适用于高度信任的 Client,比如硬件设备,系统级App

  • 客户端凭证

最后一种方式是客户端凭证(client credentials)

适用于没有前端的命令行应用,即在命令行下请求令牌,比如 Azure CLI,AWS CLI ......

  • 设备流

OAuth 2.0 还有一种遗留模式,Device Authorization Flow,使用受输入限制的设备连接到 Internet,而不是直接对用户进行身份验证,该设备会要求用户转到其计算机或智能手机上的链接并授权该设备。对于没有简单输入文字方式的设备,这避免了较差的用户体验。为此,设备应用程序使用设备授权流程(在 OAuth 2.0 中已批准),在设备授权流程中,它们传递其客户端 ID 来启动授权过程并获得令牌。

实践


接下来的几篇文章,我们就用 .NET Core 分别来实现这几种模式,以加深我们对 OAuth 2.0 的授权机制。

评论