OAuth 2.0 授权介绍和使用
这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。 第一步,A 网站提供一个链接,用户点击后就会跳转到 B 网站,授权用户数据给 A 网站使用。下面就是 A 网站跳转 B 网站的一个示意链接。 上面 URL 中, response_type 参数表示要求返回授权码( code ), client_id 参数让 B 知道是谁在请求, redirect_uri 参数是 B 接受或拒绝请求后的跳转网址, scope 参数表示要求的授权范围(这里是只读)。 第二步,用户跳转后,B 网站会要求用户登录,然后询问是否同意给予 A 网站授权。用户表示同意,这时 B 网站就会跳回 redirect_uri 参数指定的网址。跳转时,会传回一个授权码,就像下面这样。 上面 URL 中, code 参数就是授权码。 第三步,A 网站拿到授权码以后,就可以在后端,向 B 网站请求令牌。 上面 URL 中, client_id 参数和 client_secret 参数用来让 B 确认 A 的身份( client_secret 参数是保密的,因此只能在后端发请求), grant_type 参数的值是 AUTHORIZATION_CODE ,表示采用的授权方式是授权码, code 参数是上一步拿到的授权码, redirect_uri 参数是令牌颁发后的回调网址。 第四步,B 网站收到请求以后,就会颁发令牌。具体做法是向 redirect_uri 指定的网址,发送一段 JSON 数据。 上面 JSON 数据中, access_token 字段就是令牌,A 网站在后端拿到了。 有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。 RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。 第一步,A 网站提供一个链接,要求用户跳转到 B 网站,授权用户数据给 A 网站使用。 上面 URL 中, response_type 参数为 token ,表示要求直接返回令牌。 第二步,用户跳转到 B 网站,登录后同意给予 A 网站授权。这时,B 网站就会跳回 redirect_uri 参数指定的跳转网址,并且把令牌作为 URL 参数,传给 A 网站。 上面 URL 中, token 参数就是令牌,A 网站因此直接在前端拿到令牌。 注意,令牌的位置是 URL 锚点(fragment),而不是查询字符串(querystring),这是因为 OAuth 2.0 允许跳转网址是 HTTP 协议,因此存在"中间人攻击"的风险,而浏览器跳转时,锚点不会发到服务器,就减少了泄漏令牌的风险。 这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。 如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。 第一步,A 网站要求用户提供 B 网站的用户名和密码。拿到以后,A 就直接向 B 请求令牌。 上面 URL 中, grant_type 参数是授权方式,这里的 password 表示"密码式", username 和 password 是 B 的用户名和密码。 第二步,B 网站验证身份通过后,直接给出令牌。注意,这时不需要跳转,而是把令牌放在 JSON 数据里面,作为 HTTP 回应,A 因此拿到令牌。 这种方式需要用户给出自己的用户名/密码,显然风险很大,因此只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。 最后一种方式是凭证式(client credentials),适用于没有前端的命令行应用,即在命令行下请求令牌。 第一步,A 应用在命令行向 B 发出请求。 上面 URL 中, grant_type 参数等于 client_credentials 表示采用凭证式, client_id 和 client_secret 用来让 B 确认 A 的身份。 第二步,B 网站验证通过以后,直接返回令牌。 这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。 A 网站拿到令牌以后,就可以向 B 网站的 API 请求数据了。 此时,每个发到 API 的请求,都必须带有令牌。具体做法是在请求的头信息,加上一个 Authorization 字段,令牌就放在这个字段里面。 上面命令中, ACCESS_TOKEN 就是拿到的令牌。 令牌的有效期到了,如果让用户重新走一遍上面的流程,再申请一个新的令牌,很可能体验不好,而且也没有必要。OAuth 2.0 允许用户自动更新令牌。 具体方法是,B 网站颁发令牌的时候,一次性颁发两个令牌,一个用于获取数据,另一个用于获取新的令牌(refresh token 字段)。令牌到期前,用户使用 refresh token 发一个请求,去更新令牌。 上面 URL 中, grant_type 参数为 refresh_token 表示要求更新令牌, client_id 参数和 client_secret 参数用于确认身份, refresh_token 参数就是用于更新令牌的令牌。B 网站验证通过以后,就会颁发新的令牌。
360oauth token是什么意思
就是先通过第三方系统才可以登陆。OAuth的解释就是对第三方应用的授权机制,使其获取用户的数据。数据所有者收到第三方请求授权后,告诉系统通过第三方应用的请求,系统就会自动生成一个令牌(token),用来替代密码,供第三方应用使用。允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。OAuth 2.0是OAuth 1.0的后一个版本,2012年10月,OAuth 2.0协议正式发布为RFC 6749。系统工程:实现系统最优化的科学。1957年前后正式定名,1960年左右形成体系。这是一门高度综合性的管理工程技术,涉及应用数学(如最优化方法、概率论、网络理论等)、基础理论(如信息论、控制论、可靠性理论等)、系统技术(如系统模拟、通信系统等)以及经济学、管理学、社会学、心理学等各种学科。系统工程的主要任务是根据总体协调的需要 ,把自然科学和社会科学中的基础思想、理论、策略、方法等从横的方面联系起来,应用现代数学和电子计算机等工具 ,对系统的构成要素、组织结构、信息交换和自动控制等功能进行分析研究,借以达到最优化设计,最优控制和最优管理的目标。
OAuth 2.0 授权认证详解
一、认识 OAuth 2.0 1.1 OAuth 2.0 应用场景 OAuth 2.0 标准目前被广泛应用在第三方登录场景中,以下是虚拟出来的角色,阐述 OAuth2 能帮我们干什么,引用阮一峰这篇理解OAuth 2.0中的例子: 有一个"云冲印"的网站,可以将用户储存在Google的照片,冲印出来。用户为了使用该服务,必须让"云冲印"读取自己储存在Google上的照片。 问题是只有得到用户的授权,Google才会同意"云冲印"读取这些照片。那么,"云冲印"怎样获得用户的授权呢? 传统方法是,用户将自己的Google用户名和密码,告诉"云冲印",后者就可以读取用户的照片了。这样的做法有以下几个严重的缺点。 1.2 名词概念 OAuth 就是为了解决上面这些问题而诞生的。在详解 OAuth 之前,需要明确一些基本的概念,从上面场景中抽象出以下概念。 第三方应用程序 Third-party application :第三方应用程序,本文中又称"客户端"(client),即上一节例子中的"云冲印"。 HTTP服务提供商 HTTP service :HTTP服务提供商,本文中简称"服务提供商",即上一节例子中的Google。 资源所有者 Resource Owner :资源所有者,本文中又称"用户"(user)。 用户代理 User Agent :用户代理,本文中就是指浏览器。 认证服务器 Authorization server :认证服务器,即服务提供商专门用来处理认证的服务器。 资源服务器 Resource server :资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。 知道了上面这些名词,就不难理解,OAuth的作用就是让"客户端"安全可控地获取"用户"的授权,从而可以和"服务商提供商"进行互动。 二、OAuth 的授权认证流程 2.1 认证思路 OAuth 在"客户端"与"服务提供商"之间,设置了一个 授权层 (authorization layer)。"客户端"不能直接登录"服务提供商",只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。 "客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。 2.2 认证流程 官方 RFC 6749 文件中的 OAuth 2.0 流程图有点晦涩,优化了 一下: 上述中的第 2 步 是关键,即用户怎样才能给于客户端授权。有了这个授权以后,客户端就可以获取令牌,进而凭令牌获取资源。 三、四种授权模式 上一小节可以得出用户对客户端的授权动作是核心,客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式: 3.1 授权码模式(authorization code) 授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。 3.2 简化模式(implicit) 有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。 3.3 密码模式(resource owner password credentials) 如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。 3.4 客户端模式(client credentials) 最后一种方式是凭证式(client credentials),适用于没有前端的命令行应用,即在命令行下请求令牌。 四、授权码模式详解 4.1 授权码模式流程 授权码模式(authorization code)是功能最完整、流程最严密安全的授权模式。它的特点就是通过客户端的 后台服务器 ,与"服务提供商"的认证服务器进行互动。 注意这种方式适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。 授权码模式流程如下: 从上述的流程描述可知,只有第 2 步需要用户进行授权操作,之后的流程都是在客户端的后台和认证服务器后台之前进行"静默"操作,对于用户来说是无感知的。 下面是上面这些步骤所需要的参数。 4.2 授权码模式流程的五个步骤 第 1 步骤 参数说明 第 1 步骤中,客户端申请认证的URI,包含以下参数: 示例 A 网站提供一个链接,用户点击后就会跳转到 B 网站,授权用户数据给 A 网站使用。下面就是 A 网站跳转 B 网站的一个示意链接: 上面 URL 中: response_type参数表示要求返回授权码(code); client_id参数让 B 网站知道是谁在请求; redirect_uri参数是 B 网站接受或拒绝请求后的跳转网址; scope参数表示要求的授权范围(这里是只读)。 第 2 步骤 第 2 步骤中,用户跳转后,B 网站会要求用户登录,然后询问是否同意给予 A 网站授权。 第 3 步骤 参数说明 第 3 步骤中,服务器回应客户端的URI,包含以下参数: 示例 在第 2 步骤用户表示同意之后,这时 B 网站就会跳回redirect_uri参数指定的网址。跳转时,会传回一个授权码,就像下面这样。 上面 URL 中,code参数就是授权码。 第 4 步骤 参数说明 第 4 步骤中,客户端向认证服务器申请令牌的HTTP请求,包含以下参数: 示例 在第 3 步骤中,A 网站拿到授权码以后,就可以在后端,向 B 网站请求令牌。 上面 URL 中: client_id参数和client_secret参数用来让 B 确认 A 的身份(client_secret参数是保密的,因此只能在后端发请求); grant_type参数的值是AUTHORIZATION_CODE,表示采用的授权方式是授权码; code参数是上一步拿到的授权码; redirect_uri参数是令牌颁发后的回调网址。 第 5 步骤 参数说明 第 5 步骤中,认证服务器发送的HTTP回复,包含以下参数: 示例 第 4 步骤中,B 网站收到请求以后,就会颁发令牌。具体做法是向redirect_uri指定的网址,发送一段 JSON 数据: 上面 JSON 数据中,access_token字段就是令牌,A 网站在后端拿到了。注意:HTTP头信息中明确指定不得缓存。 五、令牌(Token)传递方式 当客户端(第三方应用程序)拿到访问资源服务器的令牌时,便可以使用这个令牌进行资源访问了。 在第三方应用程序拿到access_token后,如何发送给资源服务器这个问题并没有在 RFC6729 文件中定义,而是作为一个单独的 RFC6750 文件中独立定义了。这里做以下简单的介绍,主要有三种方式如下: 5.1 请求头参数传递 Authorization Request Header Field,因为在HTTP应用层协议中,专门有定义一个授权使用的Request Header,所以也可以使用这种方式: 其中"Bearer "是固定的在access_token前面的头部信息。 5.2 表单编码传递 使用 Request Body 这种方式,有一个额外的要求,就是 Request Header 的Content-Type必须是固定的application/x-www-form-urlencoded,此外还有一个限制就是 不可以使用 GET 访问,这个好理解,毕竟 GET 请求是不能携带 Request Body 的。 5.3 URI 请求参数传递 URI Query Parameter,这种使用途径应该是最常见的一种方式,非常简单,比如: 在我们请求受保护的资源的 Url 后面追加一个 access_token 的参数即可。另外还有一点要求,就是 Client 需要设置以下 Request Header 的 Cache-Control:no-store ,用来阻止 access_token 不会被 Web 中间件给 log 下来,属于安全防护方面的一个考虑。 5.4 令牌的刷新 为了防止客户端使用一个令牌无限次数使用,令牌一般会有过期时间限制,当快要到期时,需要重新获取令牌,如果再重新走授权码的授权流程,对用户体验非常不好,于是 OAuth 2.0 允许用户自动更新令牌。 具体方法是,B 网站颁发令牌的时候,一次性颁发两个令牌,一个用于获取数据,另一个用于获取新的令牌(refresh token 字段)。令牌到期前,用户使用 refresh token 发一个请求,去更新令牌。 上面 URL 中: grant_type参数为refresh_token表示要求更新令牌,此处的值固定为refresh_token,必选项; client_id参数和client_secret参数用于确认身份; refresh_token参数就是用于更新令牌的令牌。 B 网站验证通过以后,就会颁发新的令牌。 注意: 第三方应用服务器拿到刷新令牌必须存于服务器,通过后台进行重新获取新的令牌,以保障刷新令牌的保密性。 六、OAuth2的安全问题 6.1 CSRF攻击 应用程序在早期使用 OAuth2 的时候爆发过不少相关的安全方面的漏洞,其实仔细分析后会发现大都都是没有严格遵循 OAuth2 的安全相关的指导造成的,相关的漏洞事件自行搜索。 其实 OAuth2 在设计之初是已经做了很多安全方面的考虑,并且在 RFC6749 中加入了一些安全方面的规范指导。比如: 安全无小事,这方面是要靠各方面(开放平台,第三方开发者)共同防范的。 6.2 攻击流程 假设有用户张三,攻击者李四,第三方"云冲印"应用(它集成了第三方社交账号登录,并且允许用户将社交账号和"云冲印"中的账号进行绑定),以及 OAuth2 服务提供者 Google。 步骤1 攻击者李四登录"云冲印"网站,并且选择绑定自己的 Google 账号 步骤2 "云冲印"网站将李四重定向到 Google,由于他之前已经登录过 Google,所以 Google 直接向他显示是否授权"云冲印"访问的页面。 步骤3 李四在点击"同意授权"之后,截获 Google 服务器返回的含有Authorization code参数的HTTP响应。 步骤4 李四精心构造一个 Web 页面,它会触发"云冲印"网站向 Google 发起令牌申请的请求,而这个请求中的Authorization Code参数正是上一步截获到的 code。 步骤5 李四将这个 Web 页面放到互联网上,等待或者诱骗受害者张三来访问。 步骤6 张三之前登录了"云冲印"网站,只是没有把自己的账号和其他社交账号绑定起来。在张三访问了李四准备的这个 Web 页面,令牌申请流程在张三的浏览器里被顺利触发,"云冲印"网站从 Google 那里获取到access_token,但是这个 token 以及通过它进一步获取到的用户信息却都是攻击者李四的。 步骤7 "云冲印"网站将李四的 Google 账号同张三的"云冲印"账号关联绑定起来,从此以后,李四就可以用自己的 Google 账号通过 OAuth 登录到张三在 "云冲印" 网站中的账号,堂而皇之的冒充张三的身份执行各种操作。 从整体上来看,本次 CSRF 攻击的时序图应该是下面这个样子的: 从上图中可以看出,造成 CSRF 攻击漏洞问题的关键点在于,OAuth2 的认证流程是分为好几步来完成的,在上一章节授权码模式流程中的流程图中的第 4步骤中,第三方应用在收到一个 GET 请求时,除了能知道当前用户的 cookie,以及 URL 中的Authorization Code之外,难以分辨出这个请求到底是用户本人的意愿,还是攻击者利用用户的身份伪造出来的请求。 于是,攻击者就能使用移花接木的手段,提前准备一个含有自己的Authorization Code的请求,并让受害者的浏览器来接着完成后续的令牌申请流程。 6.3 解决方案 要防止这样的攻击其实很容易,作为第三方应用的开发者,只需在 OAuth 认证过程中加入state参数,并验证它的参数值即可。具体细节如下: state参数在 OAuth2 认证过程中不是必选参数,因此在早期第三方应用开发者在集成 OAuth2 认证的时候很容易会忽略它的存在,导致应用易受 CSRF 攻击。所以必须对这个安全问题重视起来。 安全是双方的,需要第三方应用和资源服务提供商均要严格遵守安全规范。如 QQ 互联的 OAuth2 API 中,state 参数是强制必选的参数,授权接口是基于 HTTPS 的加密通道等;作为第三方开发者在使用消费这些服务的时候也应该重视注意安全中存在的漏洞。