OAuth:每次授权暗中保护你的那个“MAN”
摘要:OAuth是一种授权协议,允许用户在不将账号口令泄露给第三方应用的前提下,使第三方应用可以获得用户在某个web服务上存放资源的访问权限。
背景
在传统模式下,用户的客户端在访问某个web服务提供的具有一定访问限制的资源时,需要提供用于进行身份认证的凭证(credential),例如密码,accesskey等。如果存在第三方的应用需要该web服务上用户的资源,用户必须将自己的凭证共享给第三方应用,这种实践带来了一些问题:
- 第三方应用需要存放用户的凭证,且必须拿到明文(例如使用用户名和密码远程调用web服务的API),如果第三方应用被攻击,用户的凭证可能被泄露。
- 无法限制第三方应用的权限。第三方应用拿到用户凭证明文后,等于拿到了用户的所有权限,且用户无法对第三方应用在什么时间访问哪些资源进行限制,可能被越权。
- 用户无法回收对某个第三方应用的授权,除非更改密码。更改密码可能导致依赖该密码的其他第三方应用无法访问。
- 用户资源的安全性取决于安全性最弱的第三方应用(木桶理论),任何一个第三方应用被攻击,都可能导致用户的身份凭证泄露,以及存放在web服务上的资源被攻击。
基本原理
OAuth是一种授权协议,允许用户在不将账号口令泄露给第三方应用的前提下,使第三方应用可以获得用户在某个web服务上存放资源的访问权限。
例如下图,通过华为账号登录腾讯新闻应用时,并不需要将账号口令提供给腾讯新闻应用,用户只要拥有华为账号,只需要轻轻点击一下授权就可以无缝访问,在保证安全和隐私的同时带来体验上质的飞跃,体验提升的持续追求使得OAuth协议在互联网得到了非常广泛的应用。
OAuth通过引入authorization server的概念,并对授权访问过程中的几个参与方进行重新定义和角色解耦。
上面是一个非常非常抽象的流程图,仅仅为了厘清OAuth交互过程中存在哪些角色及承担的职责,实际上具体应用过程中的差异非常大。从上图大概可以看出,OAuth协议交互过程中存在四种角色:
resource owner
需要访问资源的主体,可以是人,也可以是物,指代人的时候就是我们通常说的end-user。
resource server
存放受保护资源的web服务,接收资源的访问请求并响应,resource server对请求进行鉴权。例如用户存放照片的华为终端云服务。
client
用来代理resource owner请求资源的应用程序,client访问资源需要得到resource owner的授权。例如照片美图APP,需要拉取用户存放在云服务上的照片。
authorization server
对resource owner进行身份认证和鉴权,并颁发访问凭证。例如华为账号认证服务。
其他说明
- OAuth协议当前已经发展到0版本。1.0版本已经废弃,且OAuth2.0并不能后向兼容1.0。
- OAuth协议常用于web访问,基于HTTP协议。实际上,OAuth只是定义了一种流程,以及该流程中各方的角色定义和功能职责,并不限于HTTP这一种传输通道。
- 上面的流程图中并没有介绍resource server和authorization server之间的交互,它们可能承载在同一个web服务中,也可能由不同的独立web服务承载。当resource server和authorization server各自独立时,正是因为OAuth协议没有定义其交互过程,导致OAuth协议在产品标准化和工程化中出现困难,后面会慢慢介绍。
OAuth:授权流程
接下来我们探讨一下,获取授权和获取token的几种模式,应用场景,交互过程以及API的定义。
分类
准备工作
在开始OAuth2.0的授权流程前,应用的开发者需要将应用的信息注册到authorization server,例如华为账号服务、百度开发者中心这些知名的开放平台,注册成功后得到最重要的两个参数:client_id和client_secret,这两个参数在后面介绍的几乎每种授权流程都会频繁使用。
如下图华为终端开发者联盟管理中心注册界面:
开发者进行应用注册时,一般需要提交应用类型。应用类型常见的几大类:
对于web application,开发者还需要提交redirect URI,即web application接收grant code的地址,authorization server在认证完成后重定向到此地址。
授权码流程
授权码流程是oauth2.0最常见的交互流程,甚至很多开放平台仅支持这一种流程。授权码流程示意见下图:
该流程主要适用于web应用,基于浏览器的重定向能力实现整个交互过程。
错误返回
当resource-owner拒绝client的访问请求,或者授权请求错误,authorization server将错误信息通过redirect_uri返回给client应用,除非redirect_uri本身就不正确。
参数
说明,所有参数需经过“application/x-www-form-urlencoded”编码。
隐式授权(Implicit Grant)
如上面介绍,隐式授权适用于代码运行在客户端上的应用,例如网页应用,利用浏览器的重定向能力得到resource-owner的授权。不同于授权码流程,隐式授权流程的授权请求可以直接得到access token,没有authorization code的中间过程。隐式授权过程发生在resource owner的设备上,必须有resource owner在场,且client代码不能包含client的凭证(client_secret),另外access_token返回给client时,存在暴露到同一个设备(user-agent)上其他应用的风险。
身份信息透传授权(Resource Owner Password Credentials Grant)
如果resource owner非常信任这个应用,可以将身份凭证(口令,密钥等)通过应用传递到authorization server。一般不推荐这种方式,应用可以截留用户的身份凭证明文,风险较高,RFC协议也仅建议用于存量的应用迁移到OAuth协议。个人认为,如果client本身就是authorization server,其身份验证过程这样做也是可行的,相当于authorization server的内部实现。
客户端凭证直接授权(Client Credentials Grant)
应用拿着client_id和client_secret直接从authorization server获取access token,这种流程仅用于访问应用本身的与resource owner无关的数据,不需要resource owner授权的场景,可以使用这种授权,一般都是机机接口调用。
扩展应用
不同厂商的开放平台可以扩展授权流程,以满足不能场景的需求,例如手机、平板等端侧设备应用,或者电视、游戏手柄等娱乐设备应用。
移动端和PC桌面的应用授权
对于运行在手机、平台和PC上的应用程序,也可以通过OAuth协议得到用户的授权来安全的访问用户的数据。这种场景的授权流程和web server应用非常类似,也是authorization grant模式,主要区别是此类应用需要提供本地web server或者支持应用间跳转,并提供系统内置的“browser”(例如android的intent)实现与authorization server之间的交互。
这种授权方式的交互过程和接口和上文介绍得authorization grant模式一样,唯独授权请求的redirect_uri参数有差异:
电视或输入受限设备的应用授权
当我们在使用智能电视、游戏手柄或者带液晶屏的打印机需要访问用户的数据,例如放在网盘上的照片、文档等,需要得到用户的授权,而这类设备的输入能力有限,没有浏览器进行重定向,也不方便输入账号口令等认证凭证。
此类场景的应用授权大致步骤如下:
Step1: 获取device_code
-
Java 代码
1
POST /device/code
2
Content-Type: application/x-www-form-urlencoded
3
4
client_id=client_id&response_type=device_code&scope=email%20profile
Step2: 处理authorization响应
-
Java 代码
{
"device_code": "4/4-GMMhhdfkdkfgdgegkfkfkeegjgjgj",
"user_code": "GQVQ-JKEC",
"verification_url": "https://www.google.com/device",
"qrcode_url": "http://www.google.com/device/qrcode\ddggheghehhhdddddddddddddddhgerhh", //二维码
"expires_in": 1800 // code有效期
"interval": 5 // poll的间隔
Step3: 显示user_code
可以屏幕显示verification_url和user_code,甚至如果支持的话可以显示二维码。
Step4:poll用户授权结果
APP根据第2步授权响应的interval间隔,向authorization server 拉取用户的授权结果。
-
Javascript 代码
POST /token
Content-Type: application/x-www-form-urlencoded client_id={client_id}&
client_secret={client_secret}&
code={device_code}&
grant_type=device_code
Step5: 用户打开浏览器输入verification_url和user_code,或者通过手机扫码完成登录和授权。
Step6: 处理poll 响应
Javascript 代码
{
"access_token": "1/ffffdgdg",
"expires_in": 3920,
"scope": "openid profile email",
"token_type": "Bearer",
"refresh_token": "dgegegegedgegeg" }
OAuth:API定义和扩展
在上一篇中介绍了不同场景下的应用获得租户授权的交互流程。本文主要介绍OAuth2.0协议的授权和token API定义及常见的扩展方案。OAuth2.0的所有参数都通过"urlencoded"编码,在请求头部需要增加“application/x-www-form-urlencoded”。
1. code授权请求API
适用于authorization code grant模式,应用通过浏览器将授权请求重定向给authorization server,除了通过重定向外,我认为也可以通过FORM表单提交。
1.1 参数
1.2 示例
GET /oauth2/authorize?response_type=code&
client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
1.3 扩展
看了Google的OAuth2.0接口定义,选取几个实践中比较有意义的扩展参数:
1.4 响应
authorization server完成用户身份认证并得到用户授权后,将code作为参数重定向给redirect_uri。
2. 隐式授权请求API
适用于implicit grant模式,浏览器JS直接向authorization server发送授权请求。
2.1 参数
2.2 示例
GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com
2.3 响应
认证服务器在完成用户身份认证并得到用户的授权后,将回跳到redirect_uri,并携带access_token参数。
API定义和扩展
OAuth2.0的所有参数都通过"urlencoded"编码,在请求头部需要增加“application/x-www-form-urlencoded”。
1. code授权请求API
适用于authorization code grant模式,应用通过浏览器将授权请求重定向给authorization server,除了通过重定向外,我认为也可以通过FORM表单提交。
1.1 参数
1.2 示例
GET /oauth2/authorize?response_type=code&
client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
1.3 扩展
看了Google的OAuth2.0接口定义,选取几个实践中比较有意义的扩展参数:
1.4 响应
authorization server完成用户身份认证并得到用户授权后,将code作为参数重定向给redirect_uri。
2. 隐式授权请求API
适用于implicit grant模式,浏览器JS直接向authorization server发送授权请求。
2.1 参数
2.2 示例
GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com
2.3 响应
认证服务器在完成用户身份认证并得到用户的授权后,将回跳到redirect_uri,并携带access_token参数。
本文分享自华为云社区《【系列集合篇】浅谈OAuth二三事》,原文作者:APTX-486977。
OAuth:每次授权暗中保护你的那个“MAN”的更多相关文章
- OAuth 开放授权
什么是OAuth授权? 一.什么是OAuth协议 OAuth(开放授权)是一个开放标准. 允许第三方网站在用户授权的前提下访问在用户在服务商那里存储的各种信息. 而这种授权无需将用户提供用户名和密 ...
- OAUTH开放授权
OAUTH开放授权 OAUTH开放授权为用户资源的授权提供了一个安全的.开放而又简易的标准.OAUTH的授权不会使第三方触及到用户的帐号信息例如用户名与密码等,即第三方无需使用用户的用户名与密码就可以 ...
- 在WebApi中基于Owin OAuth使用授权发放Token
如何基于Microsoft.Owin.Security.OAuth,使用Client Credentials Grant授权方式给客户端发放access token? Client Credentia ...
- 第三方登录(1)OAuth(开放授权)简介及授权过程
3个角色:服务方,开发者,用户 a.用户在第在服务注册填写个人信息, b.服务方开放OAuth, c.开发者在服务方申请第3方登录,在程序中得到令牌后,经用户同意,可得到用户的个人信息. OAuth ...
- OAuth 开放授权 Open Authorization
http://oauth.net/ http://tools.ietf.org/html/rfc6749 http://reg.163.com/help/help_oauth2.html 网易通行证O ...
- OAuth 2.0 授权认证详解
一.认识 OAuth 2.0 1.1 OAuth 2.0 应用场景 OAuth 2.0 标准目前被广泛应用在第三方登录场景中,以下是虚拟出来的角色,阐述 OAuth2 能帮我们干什么,引用阮一峰这篇理 ...
- ASP.NET Core 认证与授权[3]:OAuth & OpenID Connect认证
在上一章中,我们了解到,Cookie认证是一种本地认证方式,通常认证与授权都在同一个服务中,也可以使用Cookie共享的方式分开部署,但局限性较大,而如今随着微服务的流行,更加偏向于将以前的单体应用拆 ...
- oAuth 认证和授权原理
什么是OAuth授权? 一.什么是OAuth协议 OAuth(开放授权)是一个开放标准. 允许第三方网站在用户授权的前提下访问在用户在服务商那里存储的各种信息. 而这种授权无需将用户提供用户名和密 ...
- OAuth认证与授权
什么是OAuth授权? 一.什么是OAuth协议 OAuth(开放授权)是一个开放标准. 允许第三方网站在用户授权的前提下访问在用户在服务商那里存储的各种信息. 而这种授权无需将用户提供用户名和密 ...
随机推荐
- 济南学习D1T1_haha
[问题描述] 栈是一种强大的数据结构,它的一种特殊功能是对数组进行排序.例如,借助一个栈,依次将数组1,3,2按顺序入栈或出栈,可对其从大到小排序: 1入栈:3入栈:3出栈:2入栈:2出栈:1出栈. ...
- Core3.1 微信v3 JSAPI支付 退款
1.前言 上一篇写了<Core3.1 微信v3 JSAPI支付>,这个属于v3的接口规则,现在研究了下退款的接口我写的时候它属于v2接口规则文档.但凡微信支付文档里面写清楚点我也不会在这里 ...
- 大数据体系概览Spark、Spark核心原理、架构原理、Spark特点
大数据体系概览Spark.Spark核心原理.架构原理.Spark特点 大数据体系概览(Spark的地位) 什么是Spark? Spark整体架构 Spark的特点 Spark核心原理 Spark架构 ...
- 深信服EDR3.2.21任意代码执行
漏洞原理: dev_linkage_launch.php 为设备联动的新入口点主要是将联动的接口构造成业务统一处理的接口 主要调用 跟进 可以看到 第一个检查为 $req_url = $_SERVE ...
- Cisco的互联网络操作系统IOS和安全设备管理器SDM__路由器软、硬件知识
路由器软.硬件知识 1.路由器的组件: 组件 解释 Bootstrap 存储在ROM中的微代码,bootstrap用于在初始化阶段启动路由器.它将启动路由器然后装入IOS POST(开机自检) 存储在 ...
- SpringMVC数据校验并通过国际化显示错误信息
目录 SpringMVC数据校验并通过国际化显示错误信息 SpringMVC数据校验 在页面中显示错误信息 通过国际化显示错误信息 SpringMVC数据校验并通过国际化显示错误信息 SpringMV ...
- idea2018 快捷键
Alt+Enter将光标放到缺少包的错误提示处自动导入包Ctrl+Alt+Space光标处会有会出现界面提示需要补全的信息也可以在new完对象后使用.var后将会自动补 Ctrl+O可以选择父类的方法 ...
- 年度账单h5 移动端兼容问题以及优化建议(vue)
定时器 vue实例中定义timer多余,创建的定时器代码和销毁定时器的代码没有放在一起,通常很容易忘记去清理这个定时器,不容易维护:建议使用this.$once('hook:beforeDestory ...
- 克鲁斯卡尔算法(Kruskal算法)求最小生成树
题目传送:https://loj.ac/p/10065 1.排序函数sort,任何一种排序算法都行,下面的示例代码中,我采用的是冒泡排序算法 2.寻源函数getRoot,寻找某一个点在并查集中的根,注 ...
- Watering Grass(贪心算法)
给定一条草坪.草坪上有n个喷水装置.草坪长l米宽w米..n个装置都有每个装置的位置和喷水半径..要求出最少需要几个喷水装置才能喷满草坪..喷水装置都是装在草坪中间一条水平线上的. n sprinkle ...