OAuth2 为什么需要 Authorization Code?
emm。。。今天我搜了一下OAuth2的流程,发现无论是中文还是英文,一上来都是跟你讲,一共是五个步骤blablabla。。。
我就在想,为啥不能不要五步,OAuth2为什么中间需要一个 Authorization Code 呢?为什么不能直接:
- 向指定的OAuth服务器发起请求,并且带上回调地址
- 用户同意授权
OAuth服务器重定向到给定的回调地址并且把生成的
access_token
和refresh_token
带上+--------+ +---------------+ | |--(A)- Authorization Request ->| Resource | | | | Owner | | |<-(B)-- Authorization Grant ---| | | | +---------------+ | | | | +---------------+ | |--(C)-- Authorization Grant -->| Authorization | | Client | | Server | | |<-(D)----- Access Token -------| | | | +---------------+ | | | | +---------------+ | |--(E)----- Access Token ------>| Resource | | | | Server | | |<-(F)--- Protected Resource ---| | +--------+ +---------------+
结果没有哪个教程直接了当的告诉我可以。其实想到这一步是很自然的,为什么三步能做完的事情要
五步来做呢?例如,我做了一个应用,使用微博登录。第一步,到微博的OAuth2服务器,第二步,
我点击允许使用微博登录,第三步,微博的OAuth2服务器回调我给定的地址并且附带上 access_token
和 refresh_token
。
然后我去翻了 RFC6749, 才发现这是可以的。OAuth2一共有四种模式:
第一种:
- 首先用户在客户端上点击要用哪个系统的OAuth2来认证,此时客户端附上回调地址
- 用户在OAuth2服务器上选择是否授权
- 用户给予授权,OAuth2服务器重定向到第一步给定的回调地址,同时附上 Authorization Code
- 回调地址所在服务器带上 Authorization Code向OAuth2服务器申请
access_token
和refresh_token
- OAuth2服务器返回
access_token
和refresh_token
第二种:
- 用户在客户端上点击要哪个系统的OAuth2来认证,此时客户端附上回调地址
- 用户在OAuth2服务器上选择是否授权
- 用户给于授权,OAuth2服务器重定向到第一步给定的回调地址,并且附上
access_token
和refresh_token
第三种:
- 用户直接输入用户名和密码,这种情况针对自家的APP或者100%信任的APP可以这么干
第四种:
- 客户端自带认证,用户向客户端认证就可以
后来看完RFC发现这样一个特点,一般第二种是用于浏览器的,第一种是用于APP的。其实我觉得没差。因为HTTP
请求里的所有字段都可以伪造呀,服务器很难分清楚到底是来自APP还是浏览器的吧。唯一一个想得到的说的通的
原因就是:第一种方式OAuth2服务器具有更强的控制权 。为什么呢?第一种方式里,可以要求客户端预先
在OAuth2服务器上注册,获得 client_id
或者是 app_secret
。然后:
- 首先用户在客户端上点击要用哪个系统的OAuth2来认证,此时客户端附上回调地址
- 用户在OAuth2服务器上选择是否授权
- 用户给予授权,OAuth2服务器重定向到第一步给定的回调地址,同时附上 Authorization Code
- 回调地址所在服务器带上 Authorization Code和回调地址,
app_secret
向OAuth2服务器申请access_token
和refresh_token
- OAuth2服务器返回
access_token
和refresh_token
这样OAuth2服务器可以知道用户到底在谁家(哪个客户端提供商)上授权。而第二种模式就不能这么做,因为
OAuth2服务器返回了 access_token
和 refresh_token
之后,谁都可以拿着这两个东西去访问资源。
第一种模式为什么知道?因为在第三步的时候,OAuth2服务器只是返回一个Authorization Code,然后客户端
拿着这个Code和自己的 app_secret
去申请 access_token
和 refresh_token
。这也就意味着,服务器
可以在这个时候记录下 app_secret
和 access_token
的关联关系。
不过,这只是我的猜想,我也不知道设计者咋想的,是不是这样的。
更多文章
- socks5 协议详解
- zerotier简明教程
- 搞定面试中的系统设计题
- frp 源码阅读与分析(一):流程和概念
- 用peewee代替SQLAlchemy
- Golang(Go语言)中实现典型的fork调用
- DNSCrypt简明教程
- 一个Gunicorn worker数量引发的血案
- Golang validator使用教程
- Docker组件介绍(二):shim, docker-init和docker-proxy
- Docker组件介绍(一):runc和containerd
- 使用Go语言实现一个异步任务框架
- 协程(coroutine)简介 - 什么是协程?
- SQLAlchemy简明教程
- Go Module 简明教程