归档

OAuth 2.0-授权码模式(authorization code)仿微信设计(战略篇)

OAuth 2.0-授权码模式(authorization code)仿微信设计(战术篇) (DDD 领域驱动设计实现代码 Golang )

在听到 OAuth 2.0 这个名词时可能很多人只知道这个是用来授权的协议,具体是怎么实现的,以及解决了什么问题,可能大家还不是很了解,下面我给大家一个场景来体会下

假设我们有个 APP 来统计用户 github 的使用情况

  • 要从 Github 获取数据,用户必须同意把自己的 Github 信息给 APP,APP 才能得到 Github 的数据进行统计数据
  • 一般来说只有把用户名密码或者用户在 Github 的 Token ,Session 给 APP ,APP才能通过 Github 获取数据,但是当前的操作可能存在以下问题
    • Token , Session 这两兄弟的有效期不长,可能刚给了APP ,一会就又失效了
    • 给了用户名密码
      1. APP 会把用户名密码都存在自己的服务器上,要是被破解或者拖库会造成密码泄露用这个密码进行保护的资源全部有泄露的风险
      2. APP 获取了用户在 Github 的全部权限,用户没办法限制授权的范围和时间
      3. 想要回收在这个 APP 的权限,用户必须改密码,这样的话其他 APP 也不行使用了,造成很大的麻烦

什么是 OAuth 2.0

  • 在了解上面的例子后大家也应该清楚为什么会出现 OAuth 2.0 ,以及 OAuth 2.0 的作用
  • 使用方=“APP” | 提供方 = “Github” | 授权层 =“OAuth 2.0 服务”
  • 其实就是使用方与提供方之前,添加一个授权层,使用方通过与授权层的交互拿到授权 (PS: 通过授权层的控制我们就能实现对不同的使用方的授权范围和时间进行控制)
  • 使用方通过授权层获取到了令牌就可以与提供方通信了

OAuth 2.0 基本运行流程

  1. 用户打开使用方应用,应用要求用户给予授权
  2. 用户同意给予应用授权
  3. 应用使用上一步获得的授权,向授权服务器申请令牌
  4. 授权服务器对授权进行认证,确认无误后发放令牌
  5. 应用使用令牌,向提供方申请获取资源
  6. 提供方确认令牌无误,同意向应用开放资源

在运行流程中第 2 步 在OAuth 2.0 中有4种实现模式

  • 授权码模式(authorization code)
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)

实现 OAuth 2.0-授权码模式(authorization code)

  1. 授权代码授权类型适用于那些向授权服务器进行认证时可以对其客户机凭证进行保密的 OAuth 客户机,可以说授权码模式(authorization code)流程最为合理,过程最为严密的模式,安全性也最高
  2. 授权码模式(authorization code)指的是使用方应用先申请一个授权码,然后再用该码获取令牌

仿微信设计

  • A: 使用方向授权服务器发起授权申请
  • B: 用户选择是否给授权给使用方
  • C: 假设用户同意授权,授权服务器将用户导向使用方事先指定的"重定向URI"(redirection URI),同时附上一个授权码以及透传参数
  • D: 使用方收到授权码,将授权码传递给使用方服务器,使用方服务器向授权服务器申请令牌
  • E: 授权服务器核对了授权码等信息,确认无误后,返回访问令牌(access token)和更新令牌(refresh token)

步骤A: 分析

https://域名/oauth2/authorize?appid=123&redirect_uri=http://127.0.0.1:8888&response_type=code&scope=snsapi_userinfo&state=123123
参数名 备注
appid 使用方唯一标识
redirect_uri 授权后重定向的回调链接地址
response_type 返回类型,请填写code
scope 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到用户信息 )
state 重定向后会带上state参数

步骤C:分析 (步骤B:用户同意后)

https://步骤A的redirect_uri地址?code=123sdsat412wdqdqw&state=123123
参数名 备注
code 授权码,code只能使用一次,5分钟未被使用自动过期。
state 步骤A传递的state

步骤D:分析

https://域名/oauth2/access_token?grant_type=authorization_code&code=123sdsat412wdqdqw&appid=123&secret=123aseqwxq
参数名 备注
appid 使用方唯一标识
secret 颁发给使用方的秘钥
code 授权码,code只能使用一次,5分钟未被使用自动过期
grant_type 填写为authorization_code

步骤E:分析

对步骤D传递的参数进行判断,无问题后颁发访问令牌(access token)和更新令牌(refresh token)等

其他

检验授权凭证(access_token)是否有效
https://域名/oauth2/auth?openid=123&access_token=颁发给用户的access_token
参数名 备注
openid 在提供方的用户的唯一标识
access_token 访问令牌(access token)

刷新 access_token

https://域名/oauth2/refresh_token?appid=123&refresh_token=更新令牌(refresh token)&grant_type=refresh_token
参数名 备注
appid 使用方唯一标识
grant_type 填写为refresh_token
refresh_token 更新令牌(refresh token)

拉取用户信息(需scope为 snsapi_userinfo)

https://域名/oauth2/userinfo?openid=123&access_token=颁发给用户的access_token
参数名 备注
appid 使用方唯一标识
grant_type 填写为refresh_token
refresh_token 更新令牌(refresh token)