前言
OAuth(Open Authorization,开放授权)是一个开放标准的授权协议,允许用户授权第三方应用访问他们存储在资源服务上受保护的信息,而不需要将用户名和密码提供给第三方应用,解耦了认证和授权。OAuth作为一种国际标准,目前传播广泛并被持续采用。OAuth2.0是OAuth协议的延续版本,更加安全,更易于实现,但不向后兼容OAuth1.0,即完全废止了OAuth1.0。
场景举例
让朋友去自己家取东西,如果我直接给他门禁系统的密码,朋友就拥有了与我同样的权限,这样不太合适。如果我想取消朋友进入我家的权限,需要更改密码才可以,操作麻烦。
能不能有种方法,朋友可以进入我家,但是又不知道我家门禁的密码。朋友如果多次进入我家,每次都需要经过我的授权,我不授权的就进不去,我授权后才能进去。
我们设计如下方案:
第一步,在门禁系统的密码输入器下面,增加一个按钮,比如叫做"获取授权"。朋友需要首先按这个按钮,去申请授权。
第二步,朋友按下按钮以后,我的手机就会弹出提示:有人正在请求授权,并显示朋友的姓名。我确认情况属实,点击同意授权。
第三步,门禁系统得到我的确认后,向朋友发送一个进入房屋的令牌(access token),令牌是类似密码的一串数字,只在短期内有效。
第四步,朋友向门禁系统输入令牌,进入房屋。
OAuth2.0介绍
如果互联网应用需要实现上面的授权场景,肯定有许多的实现方式。而OAuth2就是实现上述目标的一种规范,也就是具体实现的指导方案。OAuth(Open Authorization,开放授权)是为用户资源的授权定义了一个安全、开放及简单的标准,第三方无需知道用户的账号及密码,就可获取到用户的授权信息。
-
OAuth2是用于REST/APIs的代理授权框架(delegated authorization framework)
-
OAuth2是基于令牌Token的授权,在无需暴露用户密码的情况下,让应用获取对用户数据有限访问权限
-
OAuth2解耦认证和授权
名词解释
-
Third-party application:第三方应用,又称"客户端"(client),如上面场景中的门禁系统。
-
Resource Owner:资源拥有者,也就是用户。
-
Http Service:服务提供商,也就是持有Resource Server的存在方。可以理解为类似微信,钉钉这样具备用户信息的服务者。
-
Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器。
-
Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。与认证服务器是不同的逻辑节点,但是在物理上,双方是可以在一起的
-
User Agent:用户代理,一般就是指的浏览器。
-
客户端凭证:Client Id和密码用于认证用户。
-
访问令牌:授权服务提供者在接收到用户请求后,颁发的访问令牌。
-
刷新令牌(Refresh Token):用于获取一个新的令牌。由于令牌的有效期比较短,一旦失效,用户需要再获取令牌的流程是比较繁琐的。为了提升用户体验,可以使用reflesh_token来获取新的令牌。
互联网场景举例
OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)。"客户端"不能直接登录"服务提供商",只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。
"客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。
【小明】授权【在线打印app】到【QQ空间】访问【小明的指定相册】,以完成打印工作。
OAuth应用场景
开放系统间授权:社交联合登录、开放API平台
比如:APP或者网页接入一些第三方应用时,时常会需要用户登录另一个合作平台,比如钉钉,QQ,微博的授权登录, 这些平台都提供了基于OAuth2的机制,你可以用这些平台的账号登录而无需在其他网站上进行注册,并授权此网站获取其账号信息,包括用户名、头像等。
现代微服务安全:单页浏览器App(HTML5/JS/无状态)、无线原生App
比如:app登录请求后台接口,为了安全认证,所有请求都带token信息,如果登录验证、请求后台数据。
企业内部应用认证授权(IAM/SSO),前后端分离单页面应用(spa)
比如:有个应用是别人开发的,你需要将系统进行整合或者数据对接,此时需要单点登录;前后端分离框架,前端请求后台数据,需要进行oauth2安全认证。
令牌和密码
令牌(token)与密码(password)的作用是一样的,都可以进入系统,但是有几点差异。
(1)令牌是短期的,到期会自动失效,用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。
(2)令牌可以被资源持有者撤销,会立即失效。以上例而言,我可以随时取消朋友的令牌,密码一般不允许被他人撤销。
(3)令牌有权限范围(scope),比如使用令牌只允许进入客厅,不允许进入卧室。对于网络服务来说,只读令牌比读写令牌更安全,而密码一般是完整权限。
上面这些设计,保证了令牌既可以让第三方应用获得权限,同时又随时可控,不会危及系统安全。这就是 OAuth 2.0 的优点。
但是只要知道了令牌,就能进入系统。系统一般不会再次确认身份,所以令牌必须保密,泄漏令牌与泄漏密码的后果是一样的。 这也是为什么令牌的有效期,一般都设置得很短的原因。
OAuth2与session、cookie机制比对
1、与session机制类似,OAuth2只是变成了token,但是session有其局限性,特别是api对接
2、还有一些终端默认是不会带cookie的,比如Android
3、OAuth2可以返回refresh_toke,让客户端在一定时间内刷新token,特别适合app一定时间内无需重复登录。
OAuth2缺点
-
协议框架太宽泛,造成各种实现的兼容性和相互操作性差
-
和OAuth1.0不兼容
-
OAuth2.0不是一个认证协议(是授权协议),OAuth2.0本身并不能告诉你任何用户信息。
OAuth四种授权模式
客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0 规定了四种获得令牌的流程,可以选择实际情况选择最适合的一种,向第三方应用颁发令牌。
-
授权码模式(authorization-code):正宗方式,支持refresh_token
-
简化模式(implicit): 为web浏览器应用设计,不支持refresh_token
-
密码模式(password): 为遗留系统设计,支持refresh_token
-
客户端模式(client credentials)为后台api服务设计,不支持refresh_token
不管哪一种授权方式,第三方应用申请令牌之前,都必须先到系统备案,说明自己的身份,然后会拿到两个身份识别码:客户端 ID(client ID 用来标识第三方应用)和客户端密钥(client secret 用来进行安全加密)。这是为了防止令牌被滥用,没有备案过的第三方应用,是不会拿到令牌的。
授权码模式
这是OAuth2最常用的一种授权许可类型,要求Client具有可公开访问的Server服务器来接受Authorization Code
-
这种模式算是正宗的oauth2的授权模式
-
设计了auth code,通过这个code再获取token
-
支持refresh token
优点 | 缺点 | 备注 |
Access token通过服务器之间进行交换,比较安全 | 请求次数比较多 | 推荐该模式 |
-
用户登录应用系统,请求跳转到认证服务器,并302返回登录认证页面;
-
用户输入账户+密码进行认证,认证服务器认证通过返回code给应用系统;
-
应用系统携带code向认证服务器换取访问令牌,认证服务器验证Client ID,code等信息,给应用系统发送访问令牌;
-
应用系统携带访问令牌查询用户登录信息,认证服务器返回用户信息,如用户名;
-
应用系统验证用户名正确,创建会话,并跳转到redirect url。
简化模式
省略掉了颁发授权码(Authorization Code)给客户端的过程,直接返回访问令牌和可选的刷新令牌。其适用于没有Server服务器来接受处理Authorization Code的第三方应用
优点 | 缺点 | 备注 |
请求次数比较少,简单 | 1.没有获取code的过程, Access token直接从授权服务器返回给client客户端,令牌容易因为被拦截窃听而泄露 2.无法存储refresh token,不支持刷新令牌: 要么access token有效性给很长 ,要么access token过期后,让用户重新认证 | 适用于公开的浏览器单页应用 |
密码模式
这种模式再一步简化,和Authorzation Code类型下重要的区分就是省略了Authorization Request和Authorization Response。而是Client直接使用Resource owner提供的username和password来直接请求access_token(直接发起Access Token Request然后返回Access Token Response信息)。这种模式一般适用于Resource server高度信任第三方Client的情况下
优点 | 缺点 | 备注 |
请求次数比较少,简单 | 1.Client会获得用户的登录信息,除非是非常信任的应用,否则可能导致登录信息泄露。 2.没有多因子认证这样的机制 |
|
客户端模式
Client直接以自己的名义而不是Resource owner的名义去要求访问Resource server的一些受保护资源
-
适用于服务器间通信场景,直接根据client的id和密钥即可获取token,无需用户参与
-
这种模式比较合适消费api的后端服务,比如拉取一组用户信息等
-
不支持refresh token
Refresh token的初衷主要是为了用户体验不想用户重复输入账号密码来换取新token,因而设计了refresh token用于换取新token,客户端模式由于没有用户参与,而且也不需要用户账号密码,仅仅根据自己的id和密钥就可以换取新token,因而没必要refresh token.
刷新令牌
以便在访问令牌过期失效的时候可以由客户端自动获取新的访问令牌,而不是让用户再次登录授权。