OAuth 2.0授权模式
OAuth 2.0定义
OAuth 2.0授权框架支持第三方应用程序通过一些认证交互在资源所有者和HTTP服务中获取有限的访问权限,或者通过允许第三方应用程序以自己的名义获得访问权。
一句话就是 客户端通过授权服务器获取用户的授权,进而访问有限的资源。
-
协议流程
(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。
OAuth2.0 的四种授权方式
- 授权码(authorization-code)
- 隐藏式(implicit)
- 密码式(resource owner password credentials)
- 客户端凭证(client credentials)
当然不管哪种方式授权,都必须先来申请 客户端 ID(client_id)和客户端密钥(client_secret),证明你是个合法的应用。你懂的,干啥都要去办个证。
-
1.1 授权码模式(authorization code)
授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。
客户端是通过授权服务器(客户端与资源所有之间的中介)获取授权码,而不是直接从资源服务器获取。客户端将资源所有者定向到授权服务器,然后资源所有者返回客户端并携带授权码(code)。
在资源所有者携带code返回客户端之前,授权服务器授权给资源所有者获取授权。因为资源所有者仅通过授权服务器授权,资源所有者的凭据永远不会与客户端分享。
(A)用户访问客户端,后者将前者导向认证服务器。
(B)用户选择是否给予客户端授权。
(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上 一个授权码。
(D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器 上完成的,对用户不可见。
(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。
-
A 步骤(请求授权Authorization Request )
http://localhost:8060/oauth/authorize? response_type=code& client_id=javaboy& redirect_uri=http://www.baidu.com
接口名称:/oauth/authorize
接口参数:
- response_type:必选,授权类型,此处固定值“code”
- client_id:必选,客户端标识
- redirect_uri:可选,重定向URI
- scope:可选,申请的权限范围
- state:推荐,客户端维护的一个不透明值用于在请求和回调之前传递,可以指定任意值,认证服务器会原封不动的返回这个值,应用于防止跨站点请求伪造
请求成功后返回授权页面。
-
B 步骤(授权页面内部逻辑,自定义)
用户给客户端授权。在授权页面中会显示“授权”或者“拒绝”两个功能按钮,点击触发方法
接口方法:/oauth/authorize?user_oauth_approval
请求类型:POST
接口参数:
- user_oauth_approval:必选,用户授权同意或者拒绝 true/false
- scope.all:可选,上一步的scope确认 true
用户确认后重定向到uri
-
C步骤
服务器响应客户端跳转到redirect_uri并附带code,使用application / x-www-form-urlencoded格式重定向URI
http://www.baidu.com?code=adfadfa
返回参数:
code:必选,表示授权码
state:如果客户端请求中包含该参数,认证服务器的回应一个一模一样的参数
-
D步骤
http://localhost:8060/oauth/token?
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET&
grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=CALLBACK_URL
客户端向认证服务器申请令牌的HTTP请求
接口名称:/oauth/token
请求类型:POST
接口参数:
grant_type:必选,授权模式,此处固定值“authorization_code”
code:必选,授权服务器返回的授权码
redirect_uri:必选,重定向uri,如果之前此参数传递了,则此次必须一致
client_id:必选,客户端id,如果之前此参数传递了,则此次必须一致
client_secret:(客户端秘钥,此参数建议客户端后台服务器请求)
-
E步骤
返回令牌信息
返回参数:
{
"access_token": "522e63b8-ca1c-4062-9170-4d1ade74763d",
"token_type": "bearer",
"refresh_token": "41a89dff-311f-4563-a861-78846b94ceb7",
"expires_in": 7199,
"scope": "all"
}
-
1.2 简化模式(implicit )
简化模式不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。
(A)客户端将用户导向认证服务器。
(B)用户决定是否给于客户端授权。
(C)假设用户给予授权,认证服务器将用户导向客户端指定的"重定向URI",并在URI的Hash部分包含了访问令 牌。
(D)浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。
(E)资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。
(F)浏览器执行上一步获得的脚本,提取出令牌。
(G)浏览器将令牌发给客户端。
-
A步骤
http://localhost:8060/oauth/authorize? response_type=token& client_id=javaboy& redirect_uri=http://www.baidu.com
客户端发出的HTTP请求
接口名称:/oauth/authorize
接口参数:
- response_type:必选,授权类型,此处固定值“token”
- client_id:必选,客户端标识
- redirect_uri:可选,重定向URI
- scope:可选,申请的权限范围
- state:推荐,客户端维护的一个不透明值用于在请求和回调之前传递,可以指定任意值,认证服务器会原封不动的返回这个值,应用于防止跨站点请求伪造
请求成功后返回授权页面。
-
B步骤
同上
-
C步骤
返回redirect_url 附带token
https://a.com/callback#token=ACCESS_TOKEN
-
1.3 密码模式(password )
密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。
在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。
(A)用户向客户端提供用户名和密码。
(B)客户端将用户名和密码发给认证服务器,向后者请求令牌。
(C)认证服务器确认无误后,向客户端提供访问令牌。
-
B步骤
http://localhost:8080/oauth/token? grant_type=password& username=admin& password=admin& client_id=client1
请求类型:POST
接口名称:/oauth/token
请求参数:
- grant_type:表示授权类型,此处的值固定为"password",必选项。
- username:表示用户名,必选项。
- password:表示用户的密码,必选项。
- scope:表示权限范围,可选项。
-
1.4 客户端模式(client_credentials )
客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。
(A)客户端向认证服务器进行身份认证,并要求一个访问令牌。
(B)认证服务器确认无误后,向客户端提供访问令牌。
-
刷新令牌(client_credentials )
如果用户访问的时候,客户端的"访问令牌"已经过期,则需要使用"更新令牌"申请一个新的访问令牌。
(A)客户端通过向客户端进行身份验证来请求访问令牌 授权服务器并显示授权授权。
(B)授权服务器对客户端进行身份验证并验证授权授予,如果有效,则颁发访问令牌和刷新令牌。
(C)客户端向资源发出受保护的资源请求 通过显示访问令牌来访问服务器。
(D)资源服务器验证访问令牌,如果有效,服务请求。
(E)重复步骤(C)和(D),直到访问令牌过期。如果客户知道访问令牌已过期,则跳至步骤(G); 否则它将发出另一个受保护的资源请求。
(F)由于访问令牌无效,因此资源服务器返回无效的令牌错误。
阮一峰:http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
官方协议:https://tools.ietf.org/html/rfc6749#section-4.1.1