OAuth是一种开放的协议,为桌面程序和web应用提供了一种简单的,标准的方式去访问需要用户授权的API服务。
OAuth中的定义
- Service Provider: 允许通过OAuth访问的web app,比如云存储服务
- User: 拥有Service Provider账户的人
- Consumer: website or app, 通过OAuth访问Service Provider,例如:云打印
- Protected Resource:Service Provider的用户数据,例如用户保存在Service Provider上的照片
- Consumer Developer:实现Consumer的个人或组织
- Consumer Key: app申请接入OAuth时从OAuth服务商获得,用于在Service Provider中标识自己
- Consumer Secret: 与key对应
- Request Token: Consumer用来获取用户授权,并交换Access Token的值
- Access Token: Consumer用来代表User获取Protected Resource
- Token Secret: Consumer用来确定Token所有权的密码
请求URLs
- Request Token URL: 获取未授权的Request Token服务地址;
- User Authorization URL: 为Consumer访问获取用户授权的服务地址;
- Access Token URL: 用授权的Request Token换取Access Token的服务地址;
部分参数
- oauth_consumer_key: app申请接入OAuth时从OAuth服务商获得的Client ID
- oauth_consumer_secret:oauth_consumer_key对应的**
- oauth_signature_method: OAuth向三个URL请求时的数字签名方法
- oauth_signature:数字签名
- oauth_timestamp: 请求时间戳
- oauth_nonce:随机字符串,用与防止请求重放攻击
- oauth_version:可选字段,默认1.0
OAuth认证过程
OAuth认证是用户在不共享凭证的前提下与Consumer共享Protect Resource的过程。OAuth使用Service Provider提供的Token代替用户凭证请求用户Protected Resource。
OAuth 授权分三步完成:
- 1,Consumer 获取未授权 Request Token
- 2,User 授权Request Token
- 3,Consumer 将Request Token替换为Access Token
1,获取未授权Request Token
Consumer向Service Provider请求未授权Request Token。这个Token的目的是获得用户授权,并且只能用来获取Access Token,获取未授权Request Token流程如下:
1.1 Consumer访问Service Provider的Request Token URL,请求信息必须签名并且包含以下字段:
- oauth_consumer_key
- oauth_signature_method
- oauth_signature
- oauth_timestamp
- oauth_nonce
- oauth_version:可选
- 附加参数
1.2 Service Provider Issues an Unauthorized Request Token
Service Provider确认签名及Consumer key。如果通过,生成一个Request Token和Token Secret,通过HTTp返回Consumer。Service Provider确保Request Token在用户授权前不能交换Access Token。返回信息:
- oauth_token
- oauth_token_secret
- 附加参数
2,获取用户授权
Consumer在获得用户授权之前不能使用Request Token。获取用户授权的过程如下:
2.1 Consumer将用户导向Service Provider
Request Token需要获得用户授权,为此Consumer需要访问User Authorization URL,并包含以下参数:
- oauth_token:可选,未授权Request Token,也可用户手动输入
- oauth_callback:可选,Consumer指定一个URL,当授权成功后,Service Provider将用户重定向到该URL
Consumer构造请求URL并通过用户浏览器重定向到该地址,如果Consumer无法自动重定向,需要告知用户如何手动访问该地址。
2.2 Service Provider任重用户并获取许可
Service Provider验证用户身份并询问用户是否授权。OAuth不指定Service Provider如何鉴定用户,但定义了必须的步骤:
- Service Provider询问用户许可前需要验证用户身份,可能要求用户先登录
- Service Provider向用户展示Consumer申请访问的资源、权限等。这些信息在申请Consumer时由Consumer Developer注册。
- 用户必须授权或否决服务提供方允许Consumer代表用户访问受保护资源。一旦用户否决,Service Provider不得允许Consumer访问受保护资源。
Service Provider根据Consumer key展示Consumer信息时,必须告知用户此信息是否可靠,展示方式不做特殊指定。
2.3 Servicve Provider将用户导向Consumer
如果用户授权,需要告知Consumer Request Token已被授权。否则告知Consumer Token被收回。
如果Consumer请求时指定了oauth_callback,则Service Provider将请求导向该URL,并包含参数:oauth_token
如果请求时不指定oauth_callback,Service Provider需要告知用户手工通知Consumer完成授权的方法。
3,授权Request Token换取Access Token
Consumer请求Access Token URL,用Request Token换取Access Token。过程包含以下步骤:
3.1 Consumer请求Access Token
Consumer 访问Access Token URL,请求需签名,且包含以下信息:
- oauth_consumer_key
- oauth_token
- oauth_signature_method
- oauth_signature
- oauth_timestamp
- oauth_nonce
- oauth_version
获取Access Token不包含附加参数,以确保令牌相关信息都是之前用户确认时存在的。
3.2 Service Provider提供Access Token
Service Provider确保:
- 请求签名验证通过
- 请求令牌未被交换过
- 请求令牌与Consumer key符合
如果成功,Service Provider生成Access Token,并通过HTTP响应,应包含以下参数:
- oauth_token
- oauth_token_secret
- 附件参数
Consumer需要保存Access Token及**,用来签署Protected Resource的访问。
4,访问Protected Resource
Consumer获取Access Token和**之后,可以访问Protected Resource,访问资源的参数文档由Service Provider提供,一般包含:
- oauth_consumer_key
- oauth_token
- oauth_signature_method
- oauth_signature
- oauth_timestamp
- oauth_nonce
- oauth_version
安全
OAuth 1.0设计完成后发现了协议存在漏洞,并在后来1.0a中修复了该漏洞。但是使用过程中发现开发人员不能很好的实现协议要求的数字签名,从而导致存在大量漏洞。于是IETF重新设计了OAuth2.0,新协议不需要签名,但是与1.0版本不兼容。
oauth_consumer_secret和oauth_token_secret应用于签名中,可以oauth_consumer_secret, oauth_token_secret编码后用”&”连接作为key。
会话固化攻击
这是OAuth 1.0中存在的漏洞:
- 1,攻击者登录他在一个合法Consumer站点的账户,获得一个request token
- 2,利用trap site让受害者授权这个request token
- 3,之后针对callback的不同,有几种不同的处理方法:
- 如果Provider站点对第二步(请求用户授权)中的callback没有限制,那么攻击者可以利用trap site将callback设为自己的站点,然后通过这个callback判断受害者何时完成授权。等到受害者授权后,攻击者继续完成获得受害者的access token
- 其他的情况下(使用预定义的静态callback、没有callback由用户手工完成授权),那么攻击者和受害者之间进行竞争,当攻击者恰好在受害者授权和访问Access Token URL的间隙访问Access Token URL,那么攻击者就获得了受害者的access token
回顾协议,攻击者要访问Protected Resource,除了Access Token之外,还要有正确的签名。签名依赖consumer_secret才和oauth_token_secret和加密算法。其中consumer_secret可能通过反编译等方式获取。OAuth服务商的签名设计普遍不规范,给攻击者提供了方便。
修补
1.0a版本对漏洞进行了修补。
- 1.0协议中callback在oauth认证的第二步(请求用户授权)中通过url参数设置并明文传输。新的1.0a协议中,callback作为oauth第一步(获取request token)的参数(oauth_callback),并参与到签名过程。此外当没有callback时,callback值必须设为oob(out-of-bound)。
- Service Provider在返回request token的同时,返回一个oauth_callback_confirmed参数,其值为true,表示Provider支持1.0a协议。
- 用户完成授权后,Provider在redirect到callback时,提供一个新的oauth_verifier参数(无法被猜测的随机字串),该参数会被用在request token换取access token的过程中。如果callback值为oob,那么Provider需要提供页面显示oauth_verifier参数值。而Consumer可以引导用户将这个参数值填入适当位置,来完成授权。
原理
- 通过预先指定callback,并将其作为request token的一部分,可以避免攻击者假造callback的情况
- 通过oauth_verifier参数,可以避免攻击者和受害者竞争访问callback页面的问题。(在使用预定义静态callback或者无callback的情况下,callback无法对攻击者保密。但因为攻击者无法获知oauth_verifier参数值,因此无法换取access token)
参考
OAuth 1.0
OAuth 1.0核心
OAuth 2.0
OAuth 2 Simplified
OAuth 1.0会话固化攻击
OAuth 2.0隐蔽重定向漏洞