OAuth2 授权

引自balckheart大神的博文

什么是OAuth2

开放授权的一个标准,旨在让用户允许第三方应用去访问改用户在某服务器中的特定私有资源,而可以不提供其在某服务器的账号密码给到第三方应用

通俗的话可以这样去理解,假如你们公司正在开发一个 第三方应用XXX,该应用会需要在微信中分享出来一个活动页,该活动需要让微信用户去参与,你们的应用需要收集到用户的姓名,头像,地域等信息,那么问题来了?你的应用如何才能拿到所有参与活动的微信用户的基本信息呢?

根据以上示例,可以将OAuth2分为四个角色:

  • Resource Owner:资源所有者 即上述中的微信用户

  • Resource Server:资源服务器 即上述中的微信服务器,提供微信用户基本信息给到第三方应用

  • Client:第三方应用客户端 即上述中你公司正在开发的第三方应用

  • Authorication Server:授权服务器 该角色可以理解为管理其余三者关系的中间层

不难看出,OAuht2 解决问题的关键在于使用授权服务器提供一个访问凭据给到第三方应用,让第三方应用可以在不知道资源所有者资源服务器上的账号和密码的情况下,能获取到资源所有者资源服务器上的受保护资源,这里的受保护资源就是微信用户的姓名以及头像等信息

OAuth2 授权流程

引用 blackheart 博主的流程图

授权流程图

拿上述的获取微信用户信息示例来说

  1. 微信用户a,访问第三方应用分享到微信中的活动页面,第三方应用即向微信授权服务器 发起授权请求以获取该微信用户a在微信服务器上的姓名,头像等基本信息(私有资源

  2. 微信授权服务器接收到第三方应用的授权请求(包含第三方应用的回调地址的),并引导用户确认授权(也可以选择用户静默授权)后,返回授权许可(code)给到第三方应用(根据授权请求传入的回调地址

  3. 第三方应用拿到授权许可code后,再次向微信授权服务器发起访问令牌的请求(携带身份app_id等)

  4. 微信授权服务器验证第三方应用的身份以及授权许可code,验证通过后将下发访问令牌access_code,此外还有刷新令牌以及令牌过期时间等信息给到第三方应用

  5. 第三方应用拿到访问令牌后向微信资源服务器发起请求资源,即请求微信用户a的姓名,头像,地域等基本信息

  6. 微信资源服务器根据访问令牌,返回微信用户a的基本信息给到第三方应用。

至此,整套授权流程结束,可以看出访问令牌是整个流程中的核心

访问令牌:可以理解为对第三方应用可以在微信资源服务器中得到微信用户a的哪些信息的一个抽象集合,微信资源服务器拿到访问令牌后就知道是哪个第三方应用需要获取哪个微信用户的什么受限资源

如何部署OAuth2

部署OAuth2之前,需要理解上述四种角色之间的关系,以及每一种角色需要提供那些功能,以及将各种安全性考虑进去等等

角色 功能 备注
认证服务器 提供授权实现 提供类似获取授权许可(code),访问令牌(access_token)等接口
资源服务器 提供第三方应用程序注册接口以及开放相应受保护资源的API 第三方应用注册,是为了保证第三方应用的来源安全性
第三方应用 申请注册成为资源服务器的第三方应用以及消费资源服务器提供的受限资源API 类似微信公众号申请操作,由授权服务器提供标识第三方应用的 app_id & app_secret
用户 不需要做什么额外的改动,只需要点击确认授权即可

一般情况下授权服务器的工作由资源服务器提供,主要提供两类接口

  • 授权接口:接受第三方应用的授权请求,引导用户到资源服务器完成登陆授权的过程
  • 获取访问令牌接口:使用授权接口提供的许可凭证来颁发用户的访问令牌给到第三方应用,或者又第三方应用更新过期的访问令牌。

除此之外,还需要提供一个让第三方应用程序注册的管理后台,当第三方应用注册后会给到第三方应用一个app_id & app_secret ,app_secret是第三方应用程序的私钥,不允许在授权过程中传递的,主要用户安全加密用。

OAuth2中的有哪些授权许可

前面的示例中,第三方应用需要首先请求授权服务器以获取到授权许可code,再通过授权许可code去请求访问令牌,OAuth2中定义了四种许可类型以扩展OAuth2的机制

  • 授权码 Authorization Code
  • 隐式许可 Implicit
  • 资源所有者密码凭证 Resource Owner Password Credentials
  • 客户端凭证 Client Credentials
Authorization Code

授权码是OAuth2中最常用的一种授权许可类型,要求第三方应用需要有可公开访问的服务器来接收授权许可code,即上述中所说的回调地址。

引用 blackheart 博主的流程图

授权码形式授权流程图

简要阐述一下各步骤

  1. 授权码请求

第三方应用使用用户代理(浏览器,或自己的服务器)访问微信授权服务器提供的一个url,该url就是提供获取授权码的url,第三方应用需要传递一下参数

    response_type:(必传)此时为"code"     
    app_id:(必传)微信服务器下发的标识第三方应用的
    redirect_uri:(必传)授权成功后的重定向地址
    scope:(可选)标识授权范围
    state:(推荐)第三方应用提供的一个字符串,微信授权服务器会原样返回

示例请求

    GET /authorize?response_type=code&app_id=wx201800a28199&state=wilson&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Foauth2&scope=user,photo HTTP/1.1
  1. 授权码返回

微信授权服务器验证第三方应用再上一步中传递的参数,确认无误后会提供一个页面给微信用户a登录或者手动确认授权操作,操作超过后微信授权服务器会根据redirect_uri重定向到该地址,并携带下发的授权许可code

类似重定向地址

    HTTP/1.1 302 Found
    Location: https://client.example.com/oauth2?code=SplxlOBeZQQYbYS6WxSbIA&state=wilson
  1. 访问令牌请求

第三方应用根据上一步拿到的授权码code以及app_id,重定向地址等参数,再次请求微信授权服务器,请求获取访问令牌access_token

    grant_type:(必传)值为"authorization_code"
    code:(必传)值为上一步获取到的授权码code
    redirect_uri:(必传)必须和第一步获取授权码中的一致
    app_id:(必传)标识第三方应用id

请求示例如下

    POST /token HTTP/1.1
    Host: server.example.com
    Content-Type: application/x-www-form-urlencoded

    grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&app_id=wx201800a28199&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Foauth2
  1. 访问令牌返回

微信授权服务器返回访问令牌和一些刷新令牌,令牌过期时间等信息给到第三方应用

返回示例如下:

    HTTP/1.1 200 OK
    Content-Type: application/json;charset=UTF-8

    {
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"example",
       "expires_in":3600, 
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", 
       "example_parameter":"example_value"
    }
  1. 受限资源获取

第三方应用根据访问令牌去微信资源服务器获取微信用户a的基本信息。

Implicit

此种授权方式是授权码方式的简化版本,其中省略了颁发授权码code给第三方应用的步骤,通过一次请求微信授权服务器直接返回访问令牌以及刷新令牌等信息,适用于没有server服务器来接受处理授权码的第三方应用

  1. 授权请求

请求参数示例

    response_type:(必填)此处值为 "token"
    app_id:(必传)微信服务器下发的标识第三方应用的
    redirect_uri:(必传)授权成功后的重定向地址
    scope:(可选)标识授权范围
    state:(推荐)第三方应用提供的一个字符串,微信授权服务器会原样返回

请求url示例

    GET /authorize?response_type=token&app_id=wx201800a28199&state=wilson&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Foauth2&scope=user,photo HTTP/1.1
  1. 授权返回

返回参数示例

    access_token: 访问令牌
    refresh_token:刷新令牌
    expire_in:过期时间

返回url示例

    HTTP/1.1 302 Found
    Location:         
    http://client.example.com/oauth2#access_token=2YotnFZFEjr1zCsicMWpAA&state=wilson&expires_in=3600
Resource Owner Password Credentials Grant

该授权模式是第三方应用直接使用微信用户a的账号+密码来直接请求微信授权服务器access_token,该模式适用于微信资源服务器高度信任第三方client的情况

  1. 访问令牌请求

请求参数示例

    grant_type:(必填)值固定为 "password"
    user_name:(必填)微信用户登录名
    password:(必填)用户登录密码
    scope:可选 标识授权范围

请求url 示例

    POST /token HTTP/1.1
    Host: server.example.com
    Content-Type: application/x-www-form-urlencoded

    grant_type=password&username=blackheart&password=1234
  1. 访问令牌返回
    HTTP/1.1 200 OK
    Content-Type: application/json;charset=UTF-8

    {
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"example",
       "expires_in":3600, 
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", 
       "example_parameter":"example_value"
    }
Client Credentials Grant

此类型更加简化,第三方应用直接使用自己的名义而不是微信用户a的名义去要求访问微信资源服务器的一些受保护资源,针对第三方应用获取微信资源服务器下的所有微信用户的信息而不是单个微信用户a的信息

  1. 授权请求(以自己的名义)

请求参数示例

    grant_type:(必填)值固定为 "client_credentials"
    scope:可选 标识授权范围
  1. 授权返回
    HTTP/1.1 200 OK
    Content-Type: application/json;charset=UTF-8

    {
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"example",
       "expires_in":3600, 
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", 
       "example_parameter":"example_value"
    }

OAuth2 刷新令牌

在上述第三方应用获取到访问令牌后,一般会同时得到一个过期时间以及刷新令牌,以在访问令牌失效时可以由第三方应用自动获取新的访问令牌,而不是由微信用户a再次授权一遍。

当访问令牌过期时,由第三方应用调用微信授权服务器的刷新令牌接口,传递以下参数即可。

    grant_type:必填 值为 "refresh_token"
    refresh_token:必填 值为第三方应用得到访问令牌同时拿到的刷新令牌
  1. 刷新令牌请求
    POST /token HTTP/1.1
     Host: server.example.com

     grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
  1. 刷新令牌返回
    HTTP/1.1 200 OK
    Content-Type: application/json;charset=UTF-8

    {
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"example",
       "expires_in":3600, 
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA", 
       "example_parameter":"example_value"
    }

这样就可以一直使用有效的访问令牌啦

OAuth2 安全问题

互联网安全应引起足够的重视,防止出现重大事故

  • 要求Authorization server进行有效的第三方应用身份验证
  • app_serect,access_token,refresh_token,code等敏感信息的安全存储(不得泄露给第三方)、传输通道的安全性(TSL的要求)
  • 维持refresh_token和第三方应用的绑定,刷新失效机制
  • 维持Authorization Code和第三方应用的绑定,这也是state参数为什么是推荐的一点,以防止CSRF
  • 保证上述各种令牌信息的不可猜测行,以防止被猜测得到
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,265评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,078评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,852评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,408评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,445评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,772评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,921评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,688评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,130评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,467评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,617评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,276评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,882评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,740评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,967评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,315评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,486评论 2 348

推荐阅读更多精彩内容