简介
Oauth
的全称是Open Authorization,是一个开放授权协议,它制定了一些标准,可以使得第三方应用无需使用用户名密码即可获得用户资源。目前很多应用都提供了第三方社交账号登录及绑定,而这背后使用的技术就是Oauth2.0
.
Oauth协议最新版本是Oauth2.0,也是目前使用最广泛的协议,所以后面介绍的Oauth主要是指Oauth2.0。
Oauth协议背景
随着分布式web service、开放平台和云计算使用的越来越多,第三方应用需要能访问到一些用户的私有资源。然而这些资源都是受保护的,所以需要使用者提供资源拥有者的私有证书(用户名/密码)
进行身份认证。
但是,如果资源拥有者
(后面简称用户)把自己的私有证书(用户名/密码)透露给第三方应用
,这样会导致很多的问题:
- 信任:要想让用户输入用户名密码,应用必须得到用户信任,一般用户是不愿把自己的用户名密码透露给第三方的
- 第三方应用要明文保存用户的私有证书(密码),以便再次使用
- 一旦有了用户名密码,第三方应用可能获得过多的资源权限,比如允许访问的资源范围和限制使用时间
- 一旦用户修改密码,第三方应用则无法使用
- 用户无法单独撤销某个第三方的访问权限,只能通过修改密码来回收所有权限
现实生活中有一个非常典型的例子就是12306抢票软件,抢票软件属于第三方应用
,它需要用户的私有证书(用户名密码)
才能为用户抢票,因为铁道部12306购票系统没有对外开放,所以如果用户想要使用抢票软件,就必须提供用户名密码给抢票软件,这也是为何出现过几次12306用户名密码泄露事件的原因。
OAuth协议采取的策略是给第三方应用
一套与用户不同的私有证书来控制其对资源的访问。
这个特殊的私有证书就是访问令牌-Access Token
,它代表了一个表示特定作用域、持续时间及其它属性的字符串。
这个Access Token
是由用户授权给第三方应用,第三方应用使用Access Token来访问服务器受保护的资源。
名词术语
在具体介绍Oauth之前先介绍一些简单的属于帮助大家更好的理解Oauth。如果一开始看不懂这些术语也不要紧,可以先跳过,等后面遇到这些术语是可以再回来参考一下。
Authentication(认证)
认证
的含义是确定who are you 。在现实世界中,警察通过对比你身份证上的照片与你的长相是否一致来确认你的身份,而在网络世界中,认证就是确定电脑面前的你是不是当前账户的拥有者。最典型的认证方式就是让用户提供用户名和密码,登陆就是最常见的认证行为。
Federated Authentication(联合认证)
很多应用都有自己的认证系统,但是还有很多应用需要依赖其它的服务来认证用户,这就是联合认证
。如单点登录、OpenID等等。
Authorization(授权)
认证是确定你是谁,而授权
是更近了一步,确定你能做什么,比如是否能够阅读相关文档、是否能够获取一个email信息。授权是认证后的进一步操作,先认证才能授权。一般的web系统也是遵循先认证后授权模式,用户先进行登录,系统再判断登录用户有何权限。
Delegated Authorization(委托授权)
委托授权
就是将权限的授予委托给其它人或应用。
Oauth中的角色
Oauth协议中涉及到很多角色,我们就拿现实中的一个例子介绍。微信开放平台为第三方应用开放了微信登录接口, 有一个第三方应用今日头条,为了提高用户体验要支持微信登录,需要得到用户的账号和头像等资源。
Client客户端
客户端指的是需要获取用户资源的第三方应用
,客户端在获取资源之前必须得到用户的允许。上面例子中今日头条就是客户端。
ResouceOwner 资源服务器(api server)
资源服务器
就是客户端要调用的用户资源所在的服务器,资源服务器一般以API的形式暴露资源给客户端。上面例子中微信的开放平台就是资源服务器,它拥有过微信用户的账号、头像登录资源。
ResourceOwner 资源拥有者
资源拥有者
指的是资源的所属用户,客户端要访问资源服务器受保护的资源,必须得到资源拥有者的授权。上面例子中的微信用户就是资源拥有者。
Authorization Server 授权服务器
授权服务器
负责认证用户登录信息,颁发token给客户端。对于小的应用提供者或者大型系统的开放平台,一般既是资源服务器又是授权服务器。上面例子中微信开放平台也是授权服务器。
Oauth1.0中关于是否签名的争议
其实在OAuth2.0之前还有一个Oauth1.0。在Oauth1.0中,客户端的每次请求都需要进行加密的签名。签名对于开发人员来说非常不友好,api的调用者往往更喜欢简单直接的授权协议。
Oauth1.0诞生于2007年,当时它的发明者认为只有加密的签名才能使api更加安全,因为那个时代SSL/TLS还没有兴起。但是近些年,SSL/TLS已经非常流行,成为了保障api安全的有力途径之一。
一些安全社区也渐渐弱化了对签名必要性的态度。一方面Oauth1.0加密的复杂性导致api接受程度很低,另一方面SSL/TLS变得越来越流行,这两方面因素推动了OauthWRAP(Web Resource Authorization Profiles)的发展。OauthWRAP是Oauth2.0的先驱,它降低了签名复杂度,而且又引入了bearer tokens。
尽管Oauth2.0已经在标准社区内达成共识,但仍有一些个人对弃用签名持反对态度。所以工程师们需要在安全和易用性之间寻求一个微妙的平衡。
应用注册
Oauth要求第三方应用
在请求授权之前先在授权服务器
进行注册
,这样可以更好的管理接入的第三方应用。注册应用的时候一般需要提供一些基本信息,比如应用名称、网址、logo等。另外,还需要提供一个Redirect URI,这个就是第三方应用的地址。Redirect URI
可以在用户授权完成之后重定向回你的应用。Redirect URI 授权服务器只会重定向用户到已经注册过的URI,以避免一些恶意攻击。任何的Redirect URI必须经过TLS的保护,授权服务器
应该只会重定向到https开头的URI。这样做的目的是保护token在授权过程中不被截取。
ClientID和ClientSecret
当注册完应用时,你将会收到一个ClientId
和ClientSecret
。ClientID是公共的信息,用来识别你是哪一个应用,相当于用户名,ClientID可以直接写在javascript或者源码页面里面。但是, ClientSecret必须保证绝对机密,不能泄露给其他人