【Oauth2.0笔记】简单整理概念
这几天因工作需求查看了Oauth2.0相关的文档,其实之前也是看了好几次了。
但是过几天就会忘记其原理,岁月不饶人,这记忆…ㅠㅠ
还是自己做个笔记后续方便查看。
1. Oauth2.0的出现
网上资料介绍有很多版本,我最喜欢这种解释。
有A和B两家互联网企业,现在有个需求,A公司需要访问B公司的用户信息,比如头像,照片之类的。
这时候技术上如何实现呢?
方案一:B公司提供接口
GET /photos?account=
显然这种方法是无法接受的,因为这样的话,B的用户就没有任何隐私了。
方案二:
GET /photos?account=&pwd=
貌似还可以,但是凭什么用户把自己B公司的密码存放在A公司呢?
即使存放在A公司,但是调用B公司接口的时候A公司是很容易获取到用户密码的。
为了解决这个问题,出现了Auth2.0。
这里我们先看看4个角色:
- 资源所有者:用户就是自己的资源所有者。
- 客户端:A公司的系统是客户端。
- 资源服务器:B公司就是资源服务器(存放头像的服务器)。
- 授权服务器:B公司就是授权服务器(确认用户身份,并给A服务器授权的服务器)。
以下是原版的解释,可以做参考。
* Resource Owner: The resource owner is the user who authorizes an application to access their account.
The application’s access to the user’s account is limited to the scope of the authorization granted (e.g. read or write access)
* Client: The client is the application that wants to access the user’s account.
Before it may do so, it must be authorized by the user, and the authorization must be validated by the API.
* Resource Server: The resource server hosts the protected user accounts.
* Authorization Server: The authorization server verifies the identity of the user then issues access tokens to the application.
2. Oauth2.0 授权流程
模拟整个交互过程。
用户访问A网站,A需要访问B的用户信息。这时A会打开一个页面。
这个页面就是B部署在鉴权服务器上面的一个鉴权页面,比如A想获取(假设B是腾讯)QQ头像和昵称。
这个界面是B提供的,所以所有的信息交互是用户和B在进行,跟A是没关系。
B的鉴权服务器确认了用户的身份以后,B鉴权服务器会给A发送一个令牌(access token,全局唯一的随机字符串)。
后续A请求B的时候,都会带上这个令牌,B鉴权服务器会验证这个令牌是否合法。(也可以放到HTTP的Header里面)
GET /photos?accesstoken=xxxxx
每个access token都有scope,为了限制授权资源的范围。
每个access token都有过期时间,过期了需要重新申请,被窃取也不能一直用。
3. Access Token
一般Access Token 包含着如下信息:
标识符 jti (JWT ID): 用于标识这个 JWT 的唯一标识符。
哪个用户 sub (Subject): 表示这个 JWT 的主题,通常是用户的唯一标识符。
什么时候 iat (Issued At): 时间戳。
过期时间 exp (Expiration Time): 表示这个 JWT 的过期时间戳。
授权范围 scope: 表示这个 JWT 授予的权限范围,这里包含了 openid、profile 和 offline_access。
谁发的 iss (Issuer): 表示这个 JWT 的发行者,通常是认证服务器的 URL。
授权的app aud (Audience): 表示这个 JWT 的预期接收者,通常是应用的唯一标识符。
这里再整理一次获取Access Token的流程:
1.A需要实现一个API接口:
GET /recieve_code?code=
2.A需要访问B资源的时候,A会打开一个页面,这个页面就是B提供的一个鉴权页面。
一般是B提供SDK实现这一步的功能。A打开界面你的时候把第一步的接口地址告诉B(或已经存储)。
当用户执行授权操成功后,平台就会自动调用第一步中提供的 url,并传过来一个code。
3.第一步接口获取Code后,兑换Access Token。
这时一般会获取Access Token和refresh token。
当Access Token到期以后,A可以通过refresh token再次获取新的Access Token。
这样Access Token过期以后,不用反复地做授权的操作了。
4.Refresh Token
为了防止泄露后一直有效,access token是有期限。
但是有效期,每次Access Token 到期后,重复的让用户给A授权是很麻烦的事情。
于是 Oauth2.0 引入了 refresh token 机制。
当鉴权服务器发送access token给使用方时,同时也发送一个 efresh token。
这个refresh token的有效期很长,作用是可以用来刷新access token。
这里需要注意的是如果refresh token泄露了就很麻烦了。
所以refresh token一定要保存在使用方的服务器上,而绝不能存放在移动 app、PC端软件、浏览器上,也不能在网络上随便传递。
调用refresh接口的时候,一定是从使用方服务器到鉴权服务器的https访问。
所以,refresh token 比 access token 隐蔽得多,也安全得多。
5.Authorization Code 授权原理和实现方法
Oauth 2.0有好几种授权流程,最常见的是Authorization Code。其它的可以自行查找看看。
先看流程图
图片备用地址
这里解释一下authorization code
- code一个一次性的临时凭证,它可以兑换 access token
- code是由鉴权服务器生成的一个随机且唯一的字符串
- 鉴权服务器会记录下code的生成时间、将要兑换给谁(例子里是 A)、授权的用户是谁
- 在第5步,鉴权服务器会验证A的身份,并且检查code的有效期。通过的话就会生成access token
- code是一次性的,在第5步成功兑换access token之后就会作废
- code的有效期很短,一般不会超过1,2分钟。A在第4步获取到code之后,就立刻走第5步获取Access Token。
为什么不直接获得Access Token而是先返回code?
- code 的有效期很短,留给攻击者的时间很短
- code兑换Access Token的时候鉴权服务器还会对A的身份做一次验证。
怎么验证A的身份?
当A和B决定合作,B一般会发给A一个client_id和client_secret。
A从B那里通过code兑换Access Token的时候,也需要提供client_secret做的签名。
所以攻击者哪怕劫取了code,也很难获取Access token。除非client_secret泄露了。
6.模拟获取过程
1.第一步 用户访问A
GET /photos?xxx=?
参数应该是根据业务需求来定。
2.第二步 打开授权界面
GET /oauth2/auth
常用的参数
- client_id => 需要表明调用方。必填
- redirect_uri => 传了做校验不传则使用注册的默认值。选填
- scope => 授权范围。选填
- state => CSRF攻击。A传的值B返回给A。选填
3.第三步 用户授权
这时候B会做以下验证。
- 确认用户身份
- 检查 client_id 是否合法
- 检查 redirect_url 是否和事先注册的相符
- 检查 scope。
- 通过后生成code,并跳转到redirect_url,附上code和state,state是原封不动传回。
4.第四步 A获得code
GET /recieve_code?code=
这是A要提供的接口。
在接口里获得code以后,A还需要用client_secret签名,向B请求Access Token。
5.第五步 A获得Access Token
POST /oauth2/token
常用的参数
- code 必填
- client_id 必填
- redirect_uri 选填
- hmac 用client_secret签名 必填
这时B需要做如下验证
- 检查code是否已过期
- 检查code是否已经使用过,如果是使用过,很可能已经泄漏,需要采取相关措施
- 检查client_id是否合法,client_id和code对应的client_id是否一致
- 检查 redirect_uri参数和上面调用Auth Endpoint时传的redirect_uri是否完全一致。
- 检查 hmac
- 检查都通过,废弃掉code,生成access token并返回。
6.第六步 A使用Access Token访问资源
GET /photos?access_token=xxxx
或放到Header中去调用接口,这就看怎么规定调用方式了。
7.最后
其实Oauth2.0授权方式有4种,这里只整理了最常用的 授权码 方式。
还有隐藏式,密码式和凭证式。
这里就没做整理了,后续有机会再整理整理。
欢迎大家的意见和交流
email: li_mingxie@163.com