您的位置:首页 > 其它

开放平台鉴权以及OAuth2.0介绍

2015-03-26 18:44 246 查看

OAuth2.0协议

OAuth是一个开发标准,允许用户授权第三方网站或应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的内容。

OAuth2.0不兼容1.0。

协议的参与者

RO(resourceowner):资源所有者,对资源具有授权能力的人。

RS(resourceserver):资源服务器,它存储资源,并处理对资源的访问请求。

Client:第三方应用,它获得RO的授权后便可以去访问RO的资源。

AS(authorizationserver):授权服务器,它认证RO的身份,为RO提供授权审批流程,并最终颁发授权令牌(AccessToken)。

授权方式

在开放授权中,第三方应用(Client)可能是一个Web站点,也可能是在浏览器中运行的一段JavaScript代码,还可能是安装在本地的一个应用程序。这些第三方应用都有各自的安全特性。对于Web站点来说,它与RO浏览器是分离的,它可以自己保存协议中的敏感数据,这些密钥可以不暴露给RO;对于JavaScript代码和本地安全的应用程序来说,它本来就运行在RO的浏览器中,RO是可以访问到Client在协议中的敏感数据。

OAuth2.0为了支持这些不同类型的第三方应用,提出了下面四种授权类型:

授权码(AuthorizationCodeGrant),适用于有server端的应用授权。

隐式授权(ImplicitGrant),适用于通过客户端访问的应用授权。

资源所有者密码凭证许可(ResourceOwnerPasswordCredentialsGrant),OAuth简化版,常用于移动应用认证,称为xAuth。

受保护资源的客户端授权(ClientCredentialsGrant)。

流程ResponseType(第一次请求)GrantType(第二次请求)可带RefreshToken说明
授权码codeauthorization_code常规流程
Implicittoken-适用于纯JS程序
用户认证-password客户端高度可信,且授权码流程不方便实施
客户端-client_credentials客户端高度可信,拥有被操作资源(自用型),或操作非敏感资源

AuthorizationCode授权

1.授权场景
Authorizationcode授权适用于PC,无线客户端等需要和第三方server进行交互的应用场景。使用Authorizationcode授权,第三方能够集中处理用户的授权请求和授权结果,适用于有server端的应用。

2.授权流程
Authorizationcode授权模式分为两步,首先获取authorizationcode,然后用code获取accestoken。

示意图:

+----------+
|Resource|
|Owner|
||
+----------+
^
|
(B)
+----|-----+ClientIdentifier+---------------+
|-+----(A)--&RedirectionURI---->||
|User-||Authorization|
|Agent-+----(B)--Userauthenticates--->|Server|
||||
|-+----(C)--AuthorizationCode---<||
+-|----|---++---------------+
||^v
(A)(C)||
||||
^v||
+---------+||
||>---(D)--AuthorizationCode---------'|
|Client|&RedirectionURI|
|||
||<---(E)-----AccessToken-------------------'
+---------+(w/OptionalRefreshToken)


交互图:



+--------++---------------+
||--(A)-------AuthorizationGrant--------->||
||||
||<-(B)-----------AccessToken-------------||
||&RefreshToken||
||||
||+----------+||
||--(C)----AccessToken---->||||
||||||
||<-(D)-ProtectedResource--|Resource||Authorization|
|Client||Server||Server|
||--(E)----AccessToken---->||||
||||||
||<-(F)-InvalidTokenError-||||
||+----------+||
||||
||--(G)-----------RefreshToken----------->||
||||
||<-(H)-----------AccessToken-------------||
+--------+&OptionalRefreshToken+---------------+


3.过程详解
1、获取AuthorizationCode

请求参数

client_id必须分配给应用的appid

redirect_uri必须授权回调地址,必须和应用注册的地址一致

response_type必须授权类型,此值固定为“code”

state必须client端的状态值。用于第三方应用防止CSRF攻击,成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。

scope可选授予权限范围

其他参数

如果用户成功授权,则会跳转到指定的回调地址,并在redirect_uri地址后带上AuthorizationCode和原始的state值

2、通过AuthorizationCode获取AccessToken

请求参数

client_id必须分配给应用的appid

grant_type必须授权类型,此值为:authorization_code

client_secret必须分配给应用的secret

state必须client端的状态值。用于第三方应用防止CSRF攻击,成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。

redirect_uri必须与上面一步中传入的redirect_uri保持一致

code必须上一步返回的AuthorizationCode值(必须设定此code的有效时间)

返回参数

access_token必须授权令牌

expires_in必须该access_token的有效期

refresh_token 可选 在授权自动续期步骤中,获取新的Access_Token时需要提供的参数

其他参数可选

3、[可选]权限自动续期,获取access_token

Access_token一般需要根据应用特性设定有效期,过期后需要用户重新授权或采用自动续期的方式。

请求参数

grant_type必须授权类型,在本步骤中,此值为“refresh_token”

client_id必须分配给应用的appid

refresh_token必须第二步返回的refresh_token

client_secret必须分配给应用的secret

如果授权成功,则会返回和步骤二同样的结果。

Implicit授权

1.授权场景
Implicit授权一般适用于没有server端的客户端应用,由客户端发起授权请求,保存和处理access_token,但有些应用(如web应用等)为了提高用户体验,简化授权过程,也会常采用Implicit授权方式(注意,这种授权方式没有返回refresh_token。)

2.授权流程
示意图:

+----------+
|Resource|
|Owner|
||
+----------+
^
|
(B)
+----|-----+ClientIdentifier+---------------+
|-+----(A)--&RedirectionURI--->||
|User-||Authorization|
|Agent-|----(B)--Userauthenticates-->|Server|
||||
||<---(C)---RedirectionURI----<||
||withAccessToken+---------------+
||inFragment
||+---------------+
||----(D)---RedirectionURI---->|Web-Hosted|
||withoutFragment|Client|
|||Resource|
|(F)|<---(E)-------Script---------<||
||+---------------+
+-|--------+
||
(A)(G)AccessToken
||
^v
+---------+
||
|Client|
||
+---------+

Note:Thelinesillustratingsteps(A)and(B)arebrokenintotwo
partsastheypassthroughtheuser-agent.


交互图:



+----------+
|Resource|
|Owner|
||
+----------+
v
|ResourceOwner
(A)PasswordCredentials
|
v
+---------++---------------+
||>--(B)----ResourceOwner------->||
||PasswordCredentials|Authorization|
|Client||Server|
||<--(C)----AccessToken---------<||
||(w/OptionalRefreshToken)||
+---------++---------------+


交互图:

3.过程详解
请求参数

response_type必须授权类型,在本步骤中,此值为“token”

client_id必须分配给应用的appid

redirect_uri必须授权回调地址,必须和应用注册的地址一致

scope可选授予权限范围

state必须client端的状态值。用于第三方应用防止CSRF攻击,成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。

其他参数可选

如果成功授权,则会跳转到redirect_uri指定的回调地址,并带上access_token、expires_in、state以及与应用相关的参数。注意,这种授权方式没有返回refresh_token。

ResourceOwnerPasswordCredentials

该授权方式获取accesstoken一般只有一步,类似如下GET/POST请求:https://open.xxx.com/oauth2/access_token?client_id=xxxx&client_secret=xxxxx&grant_type=password&username=xxx&password=xxx

OAuth2.0新特性

服务器角色区分:授权服务器和资源服务器

区别不同的用户类型、授权场景和授权流程

将token分为频繁传输使用但是有效时长较短的AccessToken和用于更新AccessToken的RefreshToken

定义多种token,降低资源请求的构造难度

授权过程不签名,可根据需要采用HTTPS加密传输、验证客户端密钥(通过签名)、客户端注册时预先指定callback地址等手段。

明确引入客户端注册流程:确定ClientType、callbackURL以及其它信息

引入可选的state参数,帮助客户端防范CSRF和管理状态

引入scope参数,可以进行授权范围控制

tokentype等可被扩展:bearer(HTTPS),mac(HTTP+sign),etc.

淘宝的OAuth2.0安全控制

只支持HTTPS(bears),不支持签名(签名是走以前老的授权方式)

授权过程指定的callbackURL必须与注册的callbackURL在同一个域名,或者为um:ietf:wg:oauth:2.0:oob(表示只显示授权码,不回调callbackURL)

接口分不同级别(R1,R2,W1,W2),同一Token对不同级别接口有不同的有效期

接口权限划分(item,promotion,user,etc.)

说明为何引入authorization_code?


协议设计中,为什么要使用authorization_code来交换access_token?这是读者容易想到的一个问题。也就是说,在协议的第3步,为什么不直接将access_token通过重定向方式返回给Client呢?比如:

HTTP/1.1302
Location:'target='_blank'>https://www.facebook.com/?access_token=ya29.AHES6ZSXVKYTW2VAGZtnMjD&token_type=Bearer&expires_in=3600[/code]如果直接返回access_token,协议将变得更加简洁,而且少一次Client与AS之间的交互,性能也更优。那为何不这么设计呢?协议文档[1]中并没有给出这样设计的理由,但也不难分析:(1)浏览器的redirect_uri是一个不安全信道,此方式不适合于传递敏感数据(如access_token)。因为uri可能通过HTTPreferrer被传递给其它恶意站点,也可能存在于浏览器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)。在我们理解了上述安全性考虑之后,读者也许会有豁然开朗的感觉,懂得了引入authorization_code的妙处。那么,是不是一定要引入authorization_code才能解决这些安全问题呢?当然不是。笔者将会在另一篇博文给出一个直接返回access_token的扩展授权类型解决方案,它在满足相同安全性的条件下,使协议更简洁,交互次数更少。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
章节导航