OAuth2.0 授权

前言

OAuth2.0 是目前互联网上比较流行的授权方式,GitHub、掘金等大部分网站都采用 OAuth 的方式支持第三方账号登陆。之前工作中有接触到但是没有深入的去了解其中的机制,这里根据原理做了一个小的 demo,源码地址:OAuth2-demo

官方文档

OAuth2.0 标准出自 RFC6749 The OAuth 2.0 Authorization Framework,英文文档,有兴趣的可以研读一下。

使用场景

比如我们遇到了一个错误,在 必应 上搜索了一下,出现的第一个结果来自 CSDN,点进去读了几行网站弹出登陆页面,登陆框底部就有“其他登陆方式”的选项,可以使用 QQ、微博、百度、GitHub、开放原子开源基金会等账号登陆,这样可以不用在将密码提供给 CSDN 的情况下,授权 CSDN 访问第三方网站上的用户名等一些受密码保护的信息。

角色

授权流程中几个角色:

  • 资源所有者:就是用户自己
  • 客户端:即当前使用的网站和程序
  • 认证服务器:存放受保护的数据的网站提供的身份认证
  • 资源服务器:存放受保护的数据的网站

授权方式

OAuth2.0 定义了 4 种授权方式,各种方式之间部分流程略有不同。

  1. 授权码模式
  2. 简化模式(相较于授权模式少了一步获取授权码的流程)
  3. 密码模式(直接将密码提供给客户端,一般不用)
  4. 客户端模式

授权码模式是最流程最严密的模式,用得应该是最多的。

授权流程

以授权码模式为例:

sequenceDiagram
    客户端->>资源所有者: 请求授权
    资源所有者-->客户端: 同意授权
    客户端->>认证服务器: 1️⃣ 请求授权码
    认证服务器-->客户端: 2️⃣ 授权码
    客户端->>认证服务器: 3️⃣ 使用授权码请求 token
    认证服务器-->客户端: 4️⃣ token
    客户端->>资源服务器: 5️⃣ 访问被保护的资源
    资源服务器-->客户端: 6️⃣ 被保护的资源

为了简化流程,demo 中省略了一个资源服务器。假设客户端运行在 http://localhost:8001/client,认证服务端运行在 http://localhost:8000/auth-server,每一步具体操作如下:

请求授权码

请求地址

http://localhost:8000/auth-server/authorize?response_type=code&client_id=oauth2demo-client&redirect_uri=http://localhost:8001/client/index&scope=username&state=oauth2demo-client-state

参数解释

参数 含义
response_type 授权类型为授权码模式
client_id 客户端 id
redirect_uri 服务端返回授权码时的重定向地址
scope 授权范围
state 客户端状态,自定义值

认证服务器重定向至登陆

认证服务器重定向至本站登陆页面使用账号密码进行认证。

认证服务器返回授权码

认证服务器登陆成功后给客户端返回授权码。

请求地址

http://localhost:8001/client/index?code=XXX&state=YYYY

参数解释

参数 解释
code 认证服务器生成的授权码
state 客户端请求授权码时发过去的客户端状态,原值返回,作用不明

客户端使用授权码请求 token

请求地址

http://localhost:8000/auth-server/token?grant_type=authorization_code&code=XXX&redirect_uri=http://localhost:8001/client/index&client_id=oauth2demo-client&client_secret=oauth2demo-client-secret

参数解释

参数 解释
code 认证服务器返回的授权码,只能使用一次

认证服务器返回 token

参数

参数 含义
access_token token
token_type token 类型
expires_in 多久后过期,秒为单位
refresh_token 刷新令牌
scope 授权范围

客户端使用 token 请求资源

客户端获取到 token 之后就拿着 token 向资源服务器访问对应的资源了。

请求地址

http://localhost:8000/auth-server/userInfo?accessToken=XXX

Reference