1、OAuth2.0定义
OAuth2.0是OAuth协议的延续版本,但不向前兼容OAuth 1.0(即完全废止了OAuth1.0)。 OAuth2是一个授权协议,使应用程序能够访问其它公司提供的资源,允许用户在第三方应用访问存储在其他服务器上的私密资源,而在整个过程不需要提供用户名和密码给到第三方应用,可以通过提供一个令牌(token)实现该功能,采用令牌的方式可以让用户灵活的对第三方应用授权或收回权限。
在某些情况下, OAuth2.0也可以被用来实现Web 应用系统的单点登录。我们经常看到一些网站支持第三方登录,例如天翼云官网支持qq、微信进行登录,本质上都是使用 OAuth2.0 来实现第三方授权,基于第三方应用访问用户信息的权限,那么它是如何实现的呢?接下来我们先了解OAuth2.0的四种授权模式,然后在介绍基于OAuth 2.0单点登录原理。
1.1 OAuth2.0角色说明
角色
|
说明
|
---|---|
resource owner | 资源的拥有者,通常就是用户,比如登录的用户 |
resource server | 资源服务,提供资源的服务。需要access_token才允许被调用。比如微信api,通过access_token调用它可以获取到用户的性别等信息。 |
client | 客户端,第客户端,被授权访问的应用。比如天翼云官网、IAM |
authorization server | 认证授权服务。用户登录到本服务后,可以选择授权给第三方。比如微信登录,微信认证服务就是authorization server的角色。可以颁发client code,可以通过code换取access token. 可以通过access_token认证用户。 |
2.四种授权模式
OAuth 2.0一共有四种授权模式,详细说明可参考https://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html:
授权模式 | 说明 |
客户端模式 | 客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。 |
密码模式 | 密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。 |
隐式授权模式 | 隐式授权模式不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。 |
授权码模式 | 授权码模式(authorization code)是功能最完整、流程最严密的授权模式。它的特点就是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。 |
3、IAM通过授权码模式实现天翼账号的单点登录
这里使用IAM为例,通过授权码模式实现天翼账号的单点登录。
client指IAM,Resource Owner指用户,Authonzation Server指授权服务器(这里是指天翼账号网站https://id.dlife.cn/),Resource Server指资源服务器(这里是指天翼账号网站https://id.dlife.cn/)。授权流程如图:
3.1 IAM向用户申请授权
IAM通过IAM登录页面的天翼登录按钮重定向到天翼网站登录界面https://open.e.189.cn/api/logbox/oauth2/web/unifyAccountLogin.do进行申请授权,授权url需要包含以下参数:
appId | IAM在天翼账号开放平台申请获取的应用ID |
clientType | 统一为:10010 |
format | 统一为:redirect(用于重定向接口的显示说明) |
version | 调用的接口版本号:v1.5 |
paras | 使用appSecret对所有传入参数采用XXTea加密,并且按照接口详细规范中定义的参数(除appId、clientType、format、version、sign)拼接,不要求参数顺序。 例如:paras = XXTea((a=value1&b=value2&…),appSecret) 备注:appSecret转16进制后进行加密,加密算法后的值只有数字和全大写字母 |
sign |
签名算法: sign=HMAC-SHA1(appId+clientType+format+version+paras,appSecret).toUpperCase() 备注:注意保持签名的各字段顺序正确,签名算法后的值只有数字和全大写字母 |
paras中需要加密的参数:
timeStamp | 时间戳,毫秒 |
returnURL |
重定向返回URL(returnURL如带参数,整个returnURL需进行URL编码) |
state |
用于保持请求和回调的状态,登录请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验 |
pageKey |
统一为:normal |
3.2 用户授权认证通过,返回授权码
用户授权之后,跳转到天翼网站的页面https://open.e.189.cn/api/logbox/oauth2/web/unifyAccountLogin.do,如下图所示,然后输入自己手机号码和验证码向天翼网站进行登录验证
天翼网站登录成功之后,会重定向到IAM,并返回授权码,链接如
https://returnURL?appId=a¶s=b&sign=c
其中returnURL是申请认证的参数,响应参数解析如下:
appId | IAM在天翼账号开发平台申请获取的应用ID。 |
paras | 使用appSecret对所有传入参数采用XXTea加密,并且按具体接口详细规范中定义的参数拼接,不要求参数顺序 例如:paras=XXTea((a=value1&b=value2&…),appSecret)。 |
sign | 签名算法公式:HMAC-SHA1(appId+paras,appSecret) |
paras解密得到如下数据:
result | 0:成功1:失败 |
timeStamp |
时间戳yyyy-MM-dd HH:mm:ss,其中HH 取值为00-23,时区为东八区(接入方必须判断时间戳的有效性,以防重放攻击) |
code |
使用code换取访问令牌,2分钟内一次有效(服务端调用) |
state |
用于保持请求和回调的状态 |
3.3 天翼网站授权认证通过,IAM通过授权码code,获取访问令牌token
通过https://open.e.189.cn/api/logbox/oauth2/accessToken.do和以上返回的授权码code请求访问令牌,请求参数如下:
appId |
IAM在天翼账号开放平台申请获取的应用ID |
grantType |
固定为authorization_login |
code |
访问令牌token,第三步返回 |
format |
json |
sign |
签名算法公式:HMAC-SHA1(appId+code+format+grantType,appSecret) |
3.4 天翼网站验证授权码code通过后,返回访问令牌token
IAM通过授权码请求访问令牌,天翼网站验证授权码code通过后,返回访问令牌,返回参数如下:
result |
10000:成功 其他:失败 |
msg |
错误时返回错误信息 |
timeStamp |
时间戳yyyy-MM-dd HH:mm:ss,其中HH 取值为00-23,时区为东八区(接入方必须判断时间戳的有效性,以防重放攻击) |
appId |
开发者在注册应用的时候由综合平台分发的接入应用ID。 |
accessToken |
用于查询用户信息(服务端调用) |
atExpiresIn |
accessToken的有效期,以秒为单位 |
refreshToken |
应用刷新令牌,accessToken过期后可通过刷新令牌换取新accessToken |
rfExpiresIn |
refreshToken的有效期,以秒为单位 |
openId |
应用用户唯一标识 |
3.5 使用上面返回的访问令牌获取用户开发信息
IAM通过URL:https://open.e.189.cn//api/oauth2/account/userInfo.do验证访问令牌并获取用户开放信息,请求参数如下:
accessToken | 访问令牌 |
clientId |
IAM在天翼账号开放平台申请获取的应用ID |
version |
固定1.5 |
3.6 访问令牌验证通过之后返回用户基本信息,用户完成登录
令牌验证通过之后,天翼网站返回用户的基本信息,IAM完成天翼账号的授权登录。