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