12

OAuth:每次授权暗中保护你的那个“MAN”

 3 years ago
source link: http://www.cnblogs.com/huaweiyun/p/14411834.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

摘要: OAuth是一种授权协议,允许用户在不将账号口令泄露给第三方应用的前提下,使第三方应用可以获得用户在某个web服务上存放资源的访问权限。

背景

在传统模式下,用户的客户端在访问某个web服务提供的具有一定访问限制的资源时,需要提供用于进行身份认证的凭证(credential),例如密码,accesskey等。如果存在第三方的应用需要该web服务上用户的资源,用户必须将自己的凭证共享给第三方应用,这种实践带来了一些问题:

  1. 第三方应用需要存放用户的凭证,且必须拿到明文(例如使用用户名和密码远程调用web服务的API),如果第三方应用被攻击,用户的凭证可能被泄露。
  2. 无法限制第三方应用的权限。第三方应用拿到用户凭证明文后,等于拿到了用户的所有权限,且用户无法对第三方应用在什么时间访问哪些资源进行限制,可能被越权。
  3. 用户无法回收对某个第三方应用的授权,除非更改密码。更改密码可能导致依赖该密码的其他第三方应用无法访问。
  4. 用户资源的安全性取决于安全性最弱的第三方应用(木桶理论),任何一个第三方应用被攻击,都可能导致用户的身份凭证泄露,以及存放在web服务上的资源被攻击。

基本原理

OAuth是一种授权协议,允许用户在不将账号口令泄露给第三方应用的前提下,使第三方应用可以获得用户在某个web服务上存放资源的访问权限。

例如下图,通过华为账号登录腾讯新闻应用时,并不需要将账号口令提供给腾讯新闻应用,用户只要拥有华为账号,只需要轻轻点击一下授权就可以无缝访问,在保证安全和隐私的同时带来体验上质的飞跃,体验提升的持续追求使得OAuth协议在互联网得到了非常广泛的应用。

AJ7FBjn.png!mobile

OAuth通过引入authorization server的概念,并对授权访问过程中的几个参与方进行重新定义和角色解耦。

yqYFvu2.png!mobile

上面是一个非常非常抽象的流程图,仅仅为了厘清OAuth交互过程中存在哪些角色及承担的职责,实际上具体应用过程中的差异非常大。从上图大概可以看出,OAuth协议交互过程中存在四种角色:

  • resource owner

需要访问资源的主体,可以是人,也可以是物,指代人的时候就是我们通常说的end-user。

  • resource server

存放受保护资源的web服务,接收资源的访问请求并响应,resource server对请求进行鉴权。例如用户存放照片的华为终端云服务。

  • client

用来代理resource owner请求资源的应用程序,client访问资源需要得到resource owner的授权。例如照片美图APP,需要拉取用户存放在云服务上的照片。

  • authorization server

对resource owner进行身份认证和鉴权,并颁发访问凭证。例如华为账号认证服务。

其他说明

  1. OAuth协议当前已经发展到0版本。1.0版本已经废弃,且OAuth2.0并不能后向兼容1.0。
  2. OAuth协议常用于web访问,基于HTTP协议。实际上,OAuth只是定义了一种流程,以及该流程中各方的角色定义和功能职责,并不限于HTTP这一种传输通道。
  3. 上面的流程图中并没有介绍resource server和authorization server之间的交互,它们可能承载在同一个web服务中,也可能由不同的独立web服务承载。当resource server和authorization server各自独立时,正是因为OAuth协议没有定义其交互过程,导致OAuth协议在产品标准化和工程化中出现困难,后面会慢慢介绍。

OAuth:授权流程

接下来我们探讨一下,获取授权和获取token的几种模式,应用场景,交互过程以及API的定义。

分类

Ij6fiu2.jpg!mobile

准备工作

在开始OAuth2.0的授权流程前,应用的开发者需要将应用的信息注册到authorization server,例如华为账号服务、百度开发者中心这些知名的开放平台,注册成功后得到最重要的两个参数:client_id和client_secret,这两个参数在后面介绍的几乎每种授权流程都会频繁使用。

如下图华为终端开发者联盟管理中心注册界面:

U7jy2ea.jpg!mobile

开发者进行应用注册时,一般需要提交应用类型。应用类型常见的几大类:

NJvQnmE.png!mobile

对于web application,开发者还需要提交redirect URI,即web application接收grant code的地址,authorization server在认证完成后重定向到此地址。

授权码流程

授权码流程是oauth2.0最常见的交互流程,甚至很多开放平台仅支持这一种流程。授权码流程示意见下图:

MNf2eeM.png!mobile

该流程主要适用于web应用,基于浏览器的重定向能力实现整个交互过程。

错误返回

当resource-owner拒绝client的访问请求,或者授权请求错误,authorization server将错误信息通过redirect_uri返回给client应用,除非redirect_uri本身就不正确。

参数

NjIVRjn.png!mobile

说明,所有参数需经过“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的内部实现。

BzQj2aR.png!mobile

客户端凭证直接授权(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参数有差异:

jU3Efqu.png!mobile

电视或输入受限设备的应用授权

当我们在使用智能电视、游戏手柄或者带液晶屏的打印机需要访问用户的数据,例如放在网盘上的照片、文档等,需要得到用户的授权,而这类设备的输入能力有限,没有浏览器进行重定向,也不方便输入账号口令等认证凭证。

此类场景的应用授权大致步骤如下:

NZnuuab.png!mobile

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 参数

Q3Y3mq.png!mobile

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接口定义,选取几个实践中比较有意义的扩展参数:

nQny2ea.png!mobile

1.4 响应

authorization server完成用户身份认证并得到用户授权后,将code作为参数重定向给redirect_uri。

uuAbeui.png!mobile

2. 隐式授权请求API

适用于implicit grant模式,浏览器JS直接向authorization server发送授权请求。

2.1 参数

MbmuMfn.png!mobile

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参数。

3m2y6j7.png!mobile

API定义和扩展

OAuth2.0的所有参数都通过"urlencoded"编码,在请求头部需要增加“application/x-www-form-urlencoded”。

1. code授权请求API

适用于authorization code grant模式,应用通过浏览器将授权请求重定向给authorization server,除了通过重定向外,我认为也可以通过FORM表单提交。

1.1 参数

zuARvyf.png!mobile

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接口定义,选取几个实践中比较有意义的扩展参数:

ia2iuiR.png!mobile

1.4 响应

authorization server完成用户身份认证并得到用户授权后,将code作为参数重定向给redirect_uri。

yEJ3aqf.png!mobile

2. 隐式授权请求API

适用于implicit grant模式,浏览器JS直接向authorization server发送授权请求。

2.1 参数

MrYrEvu.png!mobile

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参数。

aEbiIfe.png!mobile

本文分享自华为云社区《【系列集合篇】浅谈OAuth二三事》,原文作者:APTX-486977。

点击关注,第一时间了解华为云新鲜技术~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK