Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >OAuth 2.0 的探险之旅

OAuth 2.0 的探险之旅

作者头像
全球技术精选
发布于 2021-11-12 02:37:53
发布于 2021-11-12 02:37:53
1.7K00
代码可运行
举报
文章被收录于专栏:全球技术精选全球技术精选
运行总次数:0
代码可运行

前言

OAuth 2.0 全称是 Open Authorization 2.0, 是用于授权(authorization)的行业标准协议。OAuth 2.0 专注于客户端开发人员的简单性,同时为 Web 应用程序、桌面应用程序、移动设备应用等提供了特定的授权流程。它在2012年取代了 OAuth 1.0, 并且 OAuth 2.0 协议不向后兼容 OAuth 1.0。

需要注意的是,OAuth 2.0 是一个授权(authorization)协议,而不是身份验证(authentication )协议。

Roles 角色

首先还需要了解一些概念, 因为整个OAuth授权流程都是围绕这些抽象的概念展开的, 角色是 OAuth2.0 授权框架核心规范的一部分, OAuth 定义了以下4种角色

•Resource Owner 资源所有者, 这里通常是拥有资源权限的用户或者系统。 •Client 客户端应用, 它可以通过访问令牌(Token)访问受保护资源, 可以是Web浏览器上的网站也可以是桌面应用或者手机App。 •Authorization Server 授权服务器, 在经过用户的授权后, 向客户端应用发放访问令牌(Access Token)。 •Resource Server 资源服务器, 存放受保护资源的服务器, 接受来自客户端(Client)请求的有效访问令牌(Access Token), 然后返回对应的资源。

Client Types 客户端类型

OAuth 2.0 核心规范定义了两种客户端类型, confidential 机密的, 和 public 公开的, 区分这两种类型的方法是, 判断这个客户端是否有能力维护自己的机密性凭据(password, client_secret)。

•confidential 对于一个普通的web站点来说,虽然用户可以访问到前端页面, 但是数据都来自服务器的后端api服务, 前端只是获取授权码code, 通过 code 换取access_token 这一步是在后端的api完成的, 由于是内部的服务器, 客户端有能力维护密码或者密钥信息, 这种是机密的的客户端。 •public 对于一个没有后端的纯前端应用来说(比如SPA), 数据的展示和操作都是在前端完成的, 包括获取令牌和操作令牌, 把一个客户端密码或者密钥放在纯前端应用是不安全的, 这种是公开的客户端。

Client Authentication 客户端身份认证

前面已经说过了, OAuth 2.0 是授权协议, 那为什么还要对 OAuth 2.0 客户端进行身份验证呢?身份验证和授权有什么区别?简单说身份验证确认用户是否是本人, 而授权则是授予用户访问资源的权限, 授权的前提条件一定是要先通过身份认证, 而且接下来的内容中, 也有用到了身份认证, 为了方便理解, 所以对认证做了简单的介绍。

授权服务器对客户端进行身份验证可以保证把令牌颁发给了合法的客户端, 但是认证其实已经超出了 OAuth2.0 的协议范围, 在 [RFC 6749] 中也只是简单介绍了以下2种认证方式:

第一种是使用 HTTP Basic [RFC2617] 中定义的身份验证方案进行身份认证, 这种方式叫 client_secret_basic, 首先需要对username,password 或者 client_id, client_secret 用冒号进行拼接。

{username}:{password} 或者 {client_id}:{client_secret} 就像这样 admin:123456 然后对字符串进行Base64编码, 然后设置为请求Header中的Authorization, 注意前面要拼接一个Basic和空格, 如下

代码语言:javascript
代码运行次数:0
运行
复制

第二种方式就更简单粗暴了, 直接在请求体中添加 client_id 和 client_secret 参数, 如下

代码语言:javascript
代码运行次数:0
运行
复制

Protocol Flow 协议流程

上图是抽象的授权协议流程, 也展示了4种角色(Role)之间的交互, 具体的过程如下

(A) 客户端向资源所有者(用户)发起授权请求, 资源所有者选择授予权限或者取消, 这个过程中, 授权服务器充当中介的角色, user ---> authorization server ----> client. (B) 客户端收到授权许可(code),这是一个代表资源所有者授权的凭证。 (C) 客户端通过授权许可(code)向授权服务器发起请求, 并期望获取一个访问令牌(access token)。 (D) 授权服务器对客户端进行身份验证并验证授权许可,如果有效,则颁发访问令牌(access token)并返回。 (E) 客户端通过访问令牌向资源服务器请求受保护的资源。 (F) 资源服务器验证访问令牌, 如果有效, 则返回相应的资源。

Access Token 访问令牌

access token 是一个用来访问受保护资源的凭证, 它是由授权服务器(Authorization Server)颁发给客户端(Client)的, 通常是字符串形式, access token 拥有特定的访问范围(scope), 并且有时间限制, 访问令牌可以有不同的格式、结构, 这点并没有限制。

Refresh Token 刷新令牌

refresh token是一个用来获取access token的凭证, 同样它是由授权服务器(Authorization Server)颁发给客户端(Client)的, 刷新令牌的时效性比访问令牌要长, 当访问令牌过期的时候, 可以直接用刷新令牌去授权服务器获取新的访问令牌, 而无需重新登录。和访问令牌不同的是, 授权服务器颁发访问令牌是必须的, 而颁发刷新令牌则是可选的, 并且访问令牌还会和资源服务器交互, 而刷新令牌只和授权服务器交互。

刷新令牌的设计非常巧妙, 它是用户体验和安全两方面取舍的一个平衡。

(A) 客户端向授权服务器发起请求, 并提供授权许可。 (B) 授权服务器对客户端进行身份验证并验证授权许可,如果有效,则颁发访问令牌和刷新令牌。 (C) 客户端请求受保护资源并提供访问令牌。 (D) 资源服务器验证这个访问令牌,如果有效, 返回相应的内容。 (E) 重复步骤 (C) 和 (D),直到访问令牌过期。如果客户端知道了访问令牌已经过期,它跳到步骤(G), 如果不知道, 继续向资源服务器发起请求。 (F) 由于访问令牌无效,资源服务器返回无效的令牌错误。 (G) 客户端发起获取刷新令牌的请求, 同时要带上当前的刷新令牌。 (H) 授权服务器对客户端进行认证并验证刷新令牌,如果有效,则发出新的访问令牌和一个可选的新的刷新令牌。

Authorization Grant 授权许可

授权许可是一个资源所有者授权的凭证, 客户端通过它去获取访问令牌(access token), OAuth 2.0定义了以下四种许可模式。

•Authorization Code 授权码•Implicit 隐式•Resource Owner Password Credentials 密码•Client Credentials 客户端凭证

Authorization Code Grant 授权码模式

授权码模式是最常用的一种授权许可模式, 也是最经典的一种, 这种模式可以获取到访问令牌和刷新令牌。还有一个特点是, 授权码模式是基于Web重定向的流程。

(A) 客户端提供一个授权链接, 引导用户点击跳转到授权服务的 /authorize 端点, 如下

代码语言:javascript
代码运行次数:0
运行
复制

参数说明如下:

•response_type:必选项, 表示响应类型,此处的值固定为"code"•client_id:必选项, 客户端的身份标识•redirect_uri 可选项, 经过用户允许授权后, 授权服务器跳转到客户端的回调地址•scope 可选项, 希望用户同意授权的权限范围•state 可选项, 推荐使用, 客户端可以维护一个在请求和回调之间的状态, 授权服务器重定向到回调地址时, 会带上这个参数, state 可以防止跨站点请求伪造-CSRF攻击。

(B) 授权服务器提供授权页面, 用户选择同意授权或者拒绝来自客户端的请求, 如下所示

(C) 假如用户同意了授权, 授权服务器会通过url重定向到客户端的回调地址, 并且会带上一个授权码 code 和 state 参数(如果之前客户端的请求中传递了state参数的话)

代码语言:javascript
代码运行次数:0
运行
复制

(D) 现在已经拿到了授权码 code 并获得了用户的授权, 接下来需要用 code 来换取 访问令牌 access_token, 可以向授权服务的 /token 端点发送 POST 请求。

代码语言:javascript
代码运行次数:0
运行
复制

参数说明如下:

•grant_type: 必选项,表示授权类型, 此处的值固定为"authorization_code" •code: 必选项,授权码, 这是上一步从授权服务器传给回调地址(redirect_uri)的参数 •redirect_uri: 必选项, 客户端的回调地址, 注意要和(A)步骤中的 redirect_uri 一致。 •client_id: 必选项,客户端的身份标识

注意, 上面使用了 Http Basic 身份认证(Authorization: Basic ...), 在本文的 "客户端身份认证" 部分有介绍, 主要是为了验证 Client 的合法性。

通过code换取access_token 步骤中,还有一种比较常见的身份验证做法是, 直接在请求体中传入 client_id, client_secret, 如下:

代码语言:javascript
代码运行次数:0
运行
复制

(E) 授权服务器对 client,code 验证通过后, 会返回 access_token 和一个可选的 refresh_token, 如下:

代码语言:javascript
代码运行次数:0
运行
复制

参数介绍:

•access_token: 必选项,访问令牌 •token_type: 令牌类型, 通常是 Bearer [RFC6750], 访问受保护资源需要在请求头设置 (Authorization:Bearer ...) •expires_in: 访问令牌的有效期, 以秒为单位 •refresh_token:可选的刷新令牌

(F) 客户端使用 access_token 向资源服务器发起请求 (G) 资源服务器验证 access_token, 验证通过后, 返回受保护的资源

这里有一个问题是, 文章上面说 access_token 只是一个字符串, 那么资源服务器如何来验证该令牌?在 OAuth 2.0 核心协议中, 关于这点并没有提及。

访问令牌主要分为两种, 一种是没有意义的随机字符串, 比如 2YotnFZFEjr1zCsicMWpAA, 这种情况客户端本身是不能鉴别令牌是否有效, 只能去授权服务器发起请求来验证该令牌, 这种安全性高,但性能差, 可以参考 RFC 7662.

第二种就是很常见的 JWT 令牌, 可以参考 RFC 7519, 令牌本身就包含了一些用户信息, 资源服务器可以通过加密算法和签名验证令牌是否有效, 而且不需要和授权服务器进行交互, 但是缺点是, 如果令牌在到期前被撤销, 资源服务器是没办法知道的。

Implicit Grant 隐式授权模式

上面是隐式授权的流程图, 它和授权码模式很像, 区别在于, 授权码模式是先拿到code,然后再换取access_token, 而隐式授权只用一次请求就拿到了access_token, 通过url参数的形式返回, 令牌也直接暴露在了浏览器地址栏, 实际上这种模式是OAuth 2.0 对公开(public)的客户端的授权流程进行了优化, 上面说到了客户端分为两种, 机密的的和公开的, 因为公开的客户端没有能力维护自己的机密凭证, 所以适合这种模式, 并且授权码模式需要客户端认证 (通过code换取access_token的时候,需要使用 Http Basic认证,或者传入client_secret) , 而隐式授权在整个流程中并没有客户端认证,所以是不安全也不推荐使用的。

请求参数:

response_type 这里固定是 token

代码语言:javascript
代码运行次数:0
运行
复制

响应参数:

代码语言:javascript
代码运行次数:0
运行
复制

这里注意 access_token 实际上并不是一个url 参数, 它前面是 # 号, 表示一个fragment, # 有别于 ?? 后面的查询字符串会被网络请求发送到服务器,而 fragment 则不会发送到服务器, 但是js是可以解析到fragment的值, 也就是 access_token, 这个设计很巧妙!

Resource Owner Password Credentials Grant 密码凭证模式

密码模式就更简单粗暴了, 用户直接把账号密码告诉客户端, 客户端向授权服务器发起POST请求, 并携带用户名和密码, 授权服务器验证通过后, 返回访问令牌和可选的刷新令牌, 这种模式的特点是, 用户和客户端是高度信任的。

请求参数:

代码语言:javascript
代码运行次数:0
运行
复制

响应参数:

代码语言:javascript
代码运行次数:0
运行
复制

Client Credentials Grant 客户端凭证模式

客户端凭证模式的特点是, 客户端就是资源所有者, 客户端访问资源也不需要用户的授权, 因为这个过程中没有用户, 资源本身就属于客户端, 通过在请求体中传入 client_id,client_secret参数或者Http Basic 进行客户端认证, 这种模式很适合后端服务或者api之间调用的场景。

请求参数:

此处的 grant_type 固定是 client_credentials

代码语言:javascript
代码运行次数:0
运行
复制

响应参数:

代码语言:javascript
代码运行次数:0
运行
复制

总结

本文介绍了 OAuth 2.0 核心协议, 主要参考 RFC 6749 (The OAuth 2.0 Authorization Framework) 核心协议 , 相信读完本文, 你会发现有些流程其实是不安全的, 没错, 其中的隐式授权和密码授权模式已经不再建议使用, 因为隐式授权从一开始就没有真正安全过, 这里介绍一下背景, 当时 OAuth 2.0 出现的时间点在2010年左右, 移动端应用是全新的,单页面应用程序(SPA) 也才刚开始出现, 当时的Web生态和现在还是差别很大, 由于技术问题, 并不能使用常规的 OAuth 模式进行授权。对于现在来说, 推荐使用专门为移动设备应用而设计的 PKCE (RFC 7636) 模式, 它是OAuth 2.0 核心的一个扩展协议, 也是最近几年移动设备应用授权的最佳实践。

目前 OAuth 2.1 也是一项正在进行中的工作, 它围绕 OAuth 2.0 对其授权功能进行加强和优化, 下篇文章我会继续介绍 OAuth 2.1 的新功能。

References

•https://www.rfc-editor.org/rfc/rfc6749•https://www.rfc-editor.org/rfc/rfc6750•https://www.rfc-editor.org/rfc/rfc7662•https://www.rfc-editor.org/rfc/rfc5849•https://www.rfc-editor.org/rfc/rfc2617•https://www.rfc-editor.org/rfc/rfc7519•https://oauth.net/2/•https://www.youtube.com/watch?v=CHzERullHe8•https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-13#section-3.4

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 半栈程序员 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
OAuth 2.0 授权认证详解
点击上方“芋道源码”,选择“设为星标” 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | Java 2021 超神之路,很肝~ 中文详细注释的开源项目 RPC 框架 Dubbo 源码解析 网络应用框架 Netty 源码解析 消息中间件 RocketMQ 源码解析 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析 作业调度中间件 Elastic-Job 源码解析 分布式事务中间件 TCC-Transaction
芋道源码
2022/06/20
1.9K0
OAuth 2.0 授权认证详解
oauth2.0的学习与使用
栗子一: 小新现在想要使用一个“在线打印服务”来打印一些照片,同时小新的照片都存储在了“云网盘”上,按照传统的方式小新要怎么做呢?
向着百万年薪努力的小赵
2022/12/02
8600
OAuth2.0认证解析
OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。
FB客服
2020/11/16
4.4K0
OAuth2.0认证解析
OAuth 2.0 扩展协议之 PKCE
阅读本文前需要了解 OAuth 2.0 授权协议的相关内容, 可以参考我的上一篇文章 OAuth 2.0 的探险之旅[1]。
全球技术精选
2021/11/18
1.5K0
OAuth 2.0 扩展协议之 PKCE
OAuth2.0协议详解
更多可以访问:https://tools.ietf.org/html/rfc6749
山行AI
2019/06/28
1.5K0
OAuth2.0 认证
密码模式(Resource owner password credentials)流程
谢公子
2022/01/20
1.5K0
OAuth2.0 认证
OAuth 2.0 之 Authorization code 与 Implicit
OAuth 2.0 是用于授权的行业标准协议。我们常见的比如第三方登录、授权第三方应用获取保存在其它服务商的个人数据,这种都是 OAuth 2.0 的应用场景。
凌虚
2021/02/04
9170
[认证授权] 1.OAuth2授权
1 OAuth2解决什么问题的? 举个栗子先。小明在QQ空间积攒了多年的照片,想挑选一些照片来打印出来。然后小明在找到一家提供在线打印并且包邮的网站(我们叫它PP吧(Print Photo缩写 ?))
blackheart
2018/01/19
1.8K0
[认证授权] 1.OAuth2授权
单点登录的实现(基于 OAuth2.0 协议)
最近放假之后实现了一下单点登录,各种项目都需要账号管理系统,太麻烦了,导致各种项目都咕咕咕,懒得写(划掉)
阿龙w
2024/02/17
1K0
单点登录的实现(基于 OAuth2.0 协议)
【全栈修炼】396- OAuth2 修炼宝典
严格来说,OAuth2 不是一个标准协议,而是一个安全的授权框架。其详细描述系统中不同角色,用户,服务前端应用(如 API )以及客户端(如网站或APP)之间如何实现相互认证。
pingan8787
2019/11/05
7750
OAuth 2.0 极简教程 (The OAuth 2.0 Authorization Framework)
OAuth(开放授权)是一个开放标准,允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容,OAuth2.0 不兼容OAuth 1.0 。
一个会写诗的程序员
2020/10/29
3.1K0
OAuth 2.0 极简教程 (The OAuth 2.0 Authorization Framework)
OAuth 2.0 的四种方式
上一篇文章介绍了 OAuth 2.0 是一种授权机制,主要用来颁发令牌(token)。本文接着介绍颁发令牌的实务操作。 下面我假定,你已经理解了 OAuth 2.0 的含义和设计思想,否则请先阅读这个系列的上一篇文章。
辉哥
2019/05/17
6030
常识二Oauth2.0介绍及安全防范
OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。
码农戏码
2021/03/23
1.5K0
SpringBoot学习笔记(十五:OAuth2 )
开放授权(Open Authorization,OAuth)是一种资源提供商用于授权第三方应用代表资源所有者获取有限访问权限的授权机制。由于在整个授权过程中,第三方应用都无须触及用户的密码就可以取得部分资源的使用权限,所以OAuth是安全开放的。
三分恶
2020/07/17
9620
SpringBoot学习笔记(十五:OAuth2 )
OAuth2.0授权协议
通过用户授权,第三方服务访问用户存在其他服务上的资源,而不需用户将用户名密码直接传递的资源服务器的安全控制协议。
sucl
2019/09/05
6920
OAuth2.0授权协议
Oauth 2.0 详解
1. Oauth2简介 简介 第三方认证技术方案最主要是解决认证协议的通用标准问题,因为要实现跨系统认证,各系统之间要 遵循一定的接口协议。 OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时,任何第三方都可以 使用OAUTH认证服务,任何服务提供商都可以实现自身的OAUTH认证服务,因而OAUTH是开放的。 业界提供了OAUTH的多种实现如PHP、JavaScript,Java,Ruby等各种语言开发包,大大节约了程序员的 时间,因而OAUTH是简易的。 互联网很多服务如Open A
BUG弄潮儿
2023/02/24
2K0
Oauth 2.0 详解
【全栈修炼】OAuth2 修炼宝典
> 开放授权(OAuth)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。 —— 维基百科
pingan8787
2019/10/30
8110
Spring Security oAuth2
oAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。Spring Security 实现了 oAuth 协议。
数媒派
2022/12/01
7540
理解OAuth 2.0
  OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。   本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考
用户1289394
2018/02/28
1.1K0
理解OAuth 2.0
OAuth 2.0验证【面试+工作】
OAuth2.0验证【面试+工作】 OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。 本文对OAuth 2.0的设计思路和运行流程,
Java帮帮
2018/03/15
1.8K0
OAuth 2.0验证【面试+工作】
相关推荐
OAuth 2.0 授权认证详解
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验