每次都会忘了OAuth的流程,用到时再找文章看一遍,反复太多次,还是自己写篇笔记记录下来,也是对自己思考的一个总结吧。
前言
第三方登录/注册是现在应用一个非常常见的功能,为什么用户通常会选择三方登录,想想不外乎有两个原因:
- 用户不愿意记录太多的用户名密码,如果共用一套用户密码太不安全,如果这个应用没有做好足够的保护措施,被人黑了,那么后果可想而知;
- 懒,注册过程通常比较繁琐,填一堆信息,如果可以一键注册,当然爽了。
所以三方登录成为很多人的首选,那么,有没有什么标准和协议可以作为三方登录的基准呢?免得每个厂家(Google, GitHub ...)各自实现一种。OAuth2正式这样的一个标准/协议
OAuth 2 简述
看一下 RFC6749 标准上是怎么描述它的:
The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.
OAuth 2.0 授权框架的初衷是使第三方应用访问资源服务器,而获取资源所有者存储在资源服务器上的一部分信息的一个协议(标准)。
官方定义了四种模式:
- 授权码模式
- 密码模式
- 简化模式
- 客户端模式
流程详解
作为三方登录,授权码模式是首选的,它是当中最完整,安全的模式。
以ruby-china的三方登录为例:
ruby-china.png
当点击 GitHub 时,将跳转至 GitHub的授权页面,同时开始进入OAuth流程
流程图中,Resource Owner 就是当前用户,User-Agent 就是浏览器,Client 就是Ruby China这个网站,Authorization Server指的是GitHub的授权服务器。
-
步骤A,Ruby China 将浏览器重定向到 GitHub的授权页面
OAuth2.png
让我们来一起分析一下这个授权页面的URL
https://github.com/login/oauth/authorize?client_id=f252166dc176d078abac&redirect_uri=https%3A%2F%2Fruby-china.org%2Faccount%2Fauth%2Fgithub%2Fcallback&response_type=code&state=b7b6fca650d3e86594981cc8c792efebe6af13caaee4ce4d
其中GitHub的URL为https://github.com/login/oauth/authorize
,URL的参数(client_id
, redirect_uri
, response_type
, state
)分别如下所示:
client_id=f252166dc176d078abac
redirect_uri=https://ruby-china.org/account/auth/github/callback
response_type=code
state=b7b6fca650d3e86594981cc8c792efebe6af13caaee4ce4d
client id = RubyChina在GitHub中注册的应用ID
redirect uri = Github会将授权码附在这个url后,并使用redirect的方式重定向https://ruby-china.org/account/auth/github/callback?code=xxxxx
response type = code,code就是指当前的Auth流程为授权码模式
state = RubyChina生产的一个随机数
- 步骤B,用户点击授权
- 步骤C,在授权成功后,GitHub将返回一个授权码给浏览器,并将浏览器重定向回RubyChina,
https://ruby-china.org/account/auth/github/callback?code=xxxxx
- 步骤D,RubyChina,通过
https://ruby-china.org/account/auth/github/callback?code=xxxxx
拿到浏览器发来的授权码,此时再带着自己在GitHub注册的ClientId和Client Secret向GitHub发送post请求索取Token, - 步骤E,GitHub返回给RubyChina Access token/Refresh token。
看到这里,可能会有疑问,为什么需要这个授权码呢?Github只会给备案过的第三方应用提供数据,备案就是在Github上注册自己为一个第三方应用,注册成功后,Github会颁发ClientId和Client Secret。ClientId只是一个id而已,可以在url里进行传输,而Client Secret安全起见需要保存在第三方应用后台。这个授权码就是在保护这个Client Secret。
此时,RubyChina以及有了获取用户在GitHub存储的部分信息的能力了。它可以用该Token去获取用户的用户名,ID,头像,邮箱等信息。作为OAuth的流程,到这里就算结束了。但三方登录还没有结束。三方登录的目的是什么?是需要获取用户的完整信息完成登录或注册的功能。
那就有两个场景:
- 用户从未登录过,此时,先完成注册,在自动登录
- 用户之前已经用GitHub登录过了,那么只需要登录。
那么针对这两种场景一一进行说明:
注册
简单YY一下,肯定有一张用户表呀,拿到GitHub上的信息,创建该用户,存一条记录,那么这张用户表都有些什么信息呢?首先能肯定有个属于RubyChina的uid,其次,GitHub返回的数据里会有一个ID,暂且叫它gid吧,这个gid代表了该用户ID(但注意一下,这个ID可不是GitHub的uid,这个id在用户通过GitHub登录RubyChina是唯一的),剩下的就是一下头像,邮箱之类的信息。
注册是完成了,接下来需要自动登录,RubyChina会创建一个Session,返回给浏览器一个SessionID之类的令牌,登录完成。
登录
如果这个用户已经在RubyChina里存在了,当通过GitHub拿到的用户时,用gid查一下用户表,用户存在哟。接下来的操作就和注册时的自动登录一样了。
到此为止,便已经完成的三方登录啦。
网友评论