1.什么是OAuth
OAuth 是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用。目前,OAuth 的最新版本为 2.0
OAuth 允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth 允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享他们的访问许可或他们数据的所有内容。
OAuth 2.0 的核心概念
OAuth 2.0 主要有4类角色:
resource owner:资源所有者,指终端的“用户”(user)。
resource server:资源服务器,即服务提供商存放受保护资源。访问这些资源,需要获得访问令牌(access token)。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。如果,我们访问新浪博客网站,那么如果使用新浪博客的账号来登录新浪博客网站,那么新浪博客的资源和新浪博客的认证都是同一家,可以认为是同一个服务器。如果,我们是新浪博客账号去登录了知乎,那么显然知乎的资源和新浪的认证不是一个服务器。
client:客户端,代表向受保护资源进行资源请求的第三方应用程序。
authorization server: 授权服务器, 在验证资源所有者并获得授权成功后,将发放访问令牌给客户端。
3.OAuth 2.0 的认证流程
(A)用户打开客户端以后,客户端请求资源所有者(用户)的授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请访问令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放访问令牌。
(E)客户端使用访问令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。
其中,用户授权有四种模式:
授权码模式(authorization code)
简化模式(implicit)
密码模式(resource owner password credentials)
客户端模式(client credentials)
3.1授权码模式(authorization code): Web-server、apps
3.1.1 为何引入authorization_code?
协议设计中,为什么要使用authorization_code来交换access_token?这是读者容易想到的一个问题。也就是说,在协议的第3步,为什么不直接将access_token通过重定向方式返回给Client呢?
如果直接返回access_token,协议将变得更加简洁,而且少一次Client与AS之间的交互,性能也更优。那为何不这么设计呢?协议文档[1]中并没有给出这样设计的理由,但也不难分析:
(1) 浏览器的redirect_uri是一个不安全信道,此方式不适合于传递敏感数据(如access_token)。因为uri可能通过HTTP referrer被传递给其它恶意站点,也可能存在于浏览器cacher或log文件中,这就给攻击者盗取access_token带来了很多机会。另外,此协议也不应该假设RO用户代理的行为是可信赖的,因为RO的浏览器可能早已被攻击者植入了跨站脚本用来监听access_token。因此,access_token通过RO的用户代理传递给Client,会显著扩大access_token被泄露的风险。 但authorization_code可以通过redirect_uri方式来传递,是因为authorization_code并不像access_token一样敏感。即使authorization_code被泄露,攻击者也无法直接拿到access_token,因为拿authorization_code去交换access_token是需要验证Client的真实身份。也就是说,除了Client之外,其他人拿authorization_code是没有用的。 此外,access_token应该只颁发给Client使用,其他任何主体(包括RO)都不应该获取access_token。协议的设计应能保证Client是唯一有能力获取access_token的主体。引入authorization_code之后,便可以保证Client是access_token的唯一持有人。当然,Client也是唯一的有义务需要保护access_token不被泄露。
(2) 引入authorization_code还会带来如下的好处。由于协议需要验证Client的身份,如果不引入authorization_code,这个Client的身份认证只能通过第1步的redirect_uri来传递。同样由于redirect_uri是一个不安全信道,这就额外要求Client必须使用数字签名技术来进行身份认证,而不能用简单的密码或口令认证方式。引入authorization_code之后,AS可以直接对Client进行身份认证(见步骤4和5),而且可以支持任意的Client认证方式(比如,简单地直接将Client端密钥发送给AS)。
3.2implicit(简单模式): Browser-based apps,Mobile apps
4. 基于Web安全的考虑
OAuth协议设计不同于简单的网络安全协议的设计,因为OAuth需要考虑各种Web攻击,比如CSRF (Cross-Site Request Forgery), XSS (Cross Site Script), Clickjacking。要理解这些攻击原理,读者需要对浏览器安全(eg, Same Origin Policy, 同源策略)有基本理解。比如,在redirect_uri中引入state参数就是从浏览器安全角度考虑的,有了它就可以抵制CSRF攻击。如果没有这个参数,攻击者便可以在redirect_uri中注入攻击者提供的authorization_code或access_token,结果可能导致Client访问错误的资源(比如,将款项汇到一个错误的帐号)。
5.参考链接
OAuth 2.0 认证的原理与实践
OAuth2.0实战1(分析简书的微信登陆及实现)
OAuth 授权的工作原理是怎样的?足够安全吗?
帮你深入理解OAuth2.0协议
Oauth2.0原理