OAuth是一种授权协议。假设用户在图像服务器保存许多图片,用户需要在打印网站访问图像服务器的图片,通过OAuth协议可以在打印网站不知道图像服务器用户名和密码的情况下访问图像服务器的图片。测试
OAuth 1.0
角色
- user:用户,资源所有者。
- Service Provider:服务提供者。
- Consumer:服务消费者,客户端。
协议流程
(A) Consumer向Service Provider申请Request Token。
(B) Service Provider验证Consumer身份后,返回一个未授权的Request Token。
(C) Consumer将用户导向Service Provider。
(D) Service Provider让用户授权。
(E) 用户授权后,Service Provider向Consumer返回已授权的Request Token。
(F) Consumer向Service Provider申请Access Token。
(G) Service Provider验证Access Token和Consumer身份后,向Consumer发布Access Token。
上述流程的请求和响应参数如下:
- 申请request token,对应步骤(A):
oauth_consumer_key
oauth_signature_method
oauth_signature
oauth_timestamp
oauth_nonce
oauth_version
oauth_callback
- Service Provider返回未授权的Request Token
oauth_token
oauth_token_secret
oauth_callback_confirmed
- Consuemer将用户导向Service Provider
oauth_token
- Service Provider在用户授权后重定向到Consumer,并返回已授权的request token
oauth_token
oauth_verifier
- Consumer使用request token向Service Provider申请access token
oauth_consumer_key
oauth_token
oauth_signature_method
oauth_signature
oauth_timestamp
oauth_nonce
oauth_version
oauth_verifier
- Service Provider验证request token后,返回access token给Consumer
oauth_token
oauth_token_secret
Nonce and Timestamp
oauth_nonce,它是用来防止重放攻击的,Service Provider应该验证唯一性,不过保存所有的oauth_nonce并不现实,所以一般只保存一段时间(比如最近一小时)内的数据。
如果不验证oauth_timestamp,那么一旦攻击者拦截到某个请求后,只要等到限定时间到了,oauth_nonce再次生效后就可以把请求原样重发,签名自然也能通过,完全是一个合法请求,所以说Service Provider必须验证oauth_timestamp和系统时钟的偏差是否在可接受范围内(比如十分钟),如此才能彻底杜绝重放攻击。
OAuth 2.0
角色
- resource owner:用户,资源所有者。
- resource server:资源服务器。
- client:客户端,想访问用户保存在资源服务器的资源。
- authorization server:授权服务器,在得到用户授权后,向客户端发布访问令牌。资源服务器和授权服务器可以在同一台服务器上。
- user-agent:用户代理,指浏览器或app客户端。
协议流程
(A) 客户端向用户请求授权。
(B) 客户端收到一个
authorization grant
,表示客户端已经被授权。(C) 客户端使用
authorization grant
,向授权服务器申请access token
。(D) 授权服务器认证客户端身份以及
authorization grant
后,向客户端发布access token
。(E) 客户端使用
access token
向资源服务器申请受保护的资源。(F) 资源服务器验证
access token
。如果有效,发送请求的资源。
Authorization Grant
Authorization Grant是客户端已经获得资源所有者授权的凭证。客户端使用authorization grant
向授权服务器换取access token
。OAuth 2.0提供了四种authorization grant:Authorization Code、Implicit、Resource Owner Password Credentials、Client Credentials。
Authorization Code
本文主要讲Authorization Code,它是OAuth 2.0推荐使用的方式,其具体实现流程如下:
(A) 客户端将用户导向授权服务器。
(B) 授权服务器认证资源所有者(通过user-agent),并让用户决定是否对客户端授权。
(C) 如果用户同意授权,授权服务器重定向user-agent回到客户端,并返回一个authorization code和state。
(D) 客户端使用authorization code向授权服务器申请access token。授权服务器验证code和客户端身份。
(E) 授权服务器验证code和客户端身份,通过后,将会返回access token和一个可选的refresh token。
上述过程的请求和响应参数说明:
-
授权请求,对应(A)
- respondse_type:响应类型,填code,必填。
- client_id:客户端标识,必填。
- redirect_id:重定向URI,选填。
- scope:授权项,选填。
- state:用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验。
-
授权响应,对应(B)
- code:用于换取access token,必填。
- state:第三方程序发送时用来标识其请求的唯一性的标志。
-
access token请求,对应(D)
- grant_type:填"authorization_code",必填。
- code:用于换取access token,必填。
- redirect_uri:与(A)步骤的值一致。
- client_id:客户端唯一标识符。
-
access token响应,对应(E)
- access_token:访问令牌,用于访问受保护的资源,必填。
- refresh_token:用于更新access_token,选填。
- expires_in: 令牌有效期,必填。
- token_type:令牌类型,必填。
注意:
为什么要分两步授权,一步行不行,即客户端一次将所有信息发给授权服务器,且授权服务器得到用户授权后直接向客户端发布access token?
不行,因为向用户申请授权的时候,是经过user-agent。只有一步的话,user-agent也会拿到access token。
刷新access token
access token是有时效性的,当access token失效或过期后,客户端可以使用refresh token向授权服务器申请新的access token。
请求参数:
- grant_type:填"refresh_token",必填。
- refresh_token:用于申请access_token,必填。
- scope:授权范围,选填。
响应参数:和(E)相同。