有些客户端所在的环境是没有浏览器的。例如:智能电视、媒体控制台、数字相框、打印机等,像这类的设备,要在设备上面将用户操作引导至认证平台界面去输入账号、密码,然后确认授权,这显示不现实。解决这类设备的登录场景,最常见的就是手机扫码登录,或将认证地址发送到手机上,让用户在手机浏览器上进行认证授权。在 OAuth 2.1 中,已经加入设备授权码模式,那么本篇就来实现一下设备授权码登录。
OAuth2.1的设计背景,在于允许用户在不告知第三方自己的账号密码情况下,通过授权方式,让第三方服务可以获取自己的资源信息。 详细的协议介绍,开发者可以参考The OAuth 2.1 Authorization Framework,以及OpenID Connect Core 1.0 incorporating errata set 2。
以上图交互比较多,但是对于设备终端来说,只要关注两个步骤:
1、图中步骤1,获取设备码;
2、图中步骤5,轮询请求,间隔5秒,获取access_token;
其他所有交互,企业服务平台已经实现,设备终端不需要关注。
请求方式:POST(HTTPS) Content-Type: application/x-www-form-urlencoded
请求地址:
生产环境:https://esp.xkw.cn/oauth2/device_authorization
沙箱测试环境:https://esp.doc.xkw.cn/oauth2/device_authorization
详细说明开发者可以参考The OAuth 2.1 Authorization Framework
参数 | 必须 | 说明 |
---|---|---|
client_id | 是 | 企业服务平台分配的client_id |
scope | 是 | 授权范围,最小权限原则 |
参数 | 说明 |
---|---|
user_code | 用户码 |
device_code | 设备码 |
verification_uri_complete | 用户码验证地址,包含用户码参数 |
verification_uri | 用户码验证地址 |
expires_in | 设备码有效期,单位为秒 |
error_description | 错误描述 |
error_code | 错误码 |
error_uri | 错误详细说明地址 |
a) 成功返回示例如下:
x{
"user_code": "QWFN-VTLP",
"device_code": "sf1NvQqp3A5kmSzfTW30UwrIlz_Ey4cFyomduHY8VtOZkQ3CnYsnwAwZROiJEpxr8tIEMJ4WDgC4rookrJCZ732KEmErF6UujpiI4_eBRDFXmWH3hQpGg-FdkDwPkRCw",
"verification_uri_complete": "https://esp.doc.xkw.cn/oauth2/device_verification?user_code=QWFN-VTLP",
"verification_uri": "https://esp.doc.xkw.cn/oauth2/device_verification",
"expires_in": 300
}
b)失败返回示例如下:
{
"error_description": "client_id不正确",
"error_code": "100031",
"error_uri": "https://esp.xkw.cn/doc/error?q=error_code"
}
接口返回device_code有效期为expires_in,单位是秒,调用方要做好device_code的缓存处理,
x缓存时间 = expires_in - 60
缓存时间只要将平台返回的expires_in减去1分钟即可。
注意:不要频繁请求获取device_code,以免被限流控制;
请求方式:POST(HTTPS) Content-Type: application/x-www-form-urlencoded
请求地址:
生产环境:https://esp.xkw.cn/oauth2/token
沙箱测试环境:https://esp.doc.xkw.cn/oauth2/token
详细说明开发者可以参考The OAuth 2.1 Authorization Framework
参数 | 必须 | 说明 |
---|---|---|
client_id | 是 | 企业服务平台分配的client_id |
grant_type | 是 | 当前值为urn:ietf:params:oauth:grant-type:device_code |
device_code | 是 | 设备码,上一步返回 |
参数 | 说明 |
---|---|
access_token | 访问令牌,调用开放接口的凭证 |
refresh_token | 刷新令牌,在refresh_token有效期内,都可以对access_token进行刷新 |
scope | 授权范围,返回构造的授权链接请求中的scope |
token_type | token类型 |
expires_in | access_token有效期,单位为秒 |
error_description | 错误描述 |
error_code | 错误码 |
error_uri | 错误详细说明地址 |
a) 成功返回示例如下:
{
"access_token": "eyJraWQiOiJjM2Q2ZDAxYiIsInR5cCI6IkpXVCIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiJ4eTA3NjE5IiwiYXVkIjoiZGV2aWNlIiwibmJmIjoxNzE3ODQwNDM0LCJzY29wZSI6WyJvYSJdLCJpc3MiOiJodHRwczovL2VzcDIuZG9jLnhrdy5jbiIsImV4cCI6MTcxNzg0NDAzNCwiaWF0IjoxNzE3ODQwNDM0fQ.H-8COli2z-SmOwmdGII2qEOrg8tNygECB_LgO9ilQD2HguhLo310tvFzCUdoXVmcn1QBbs_JFjYr2DwEkvtgz9r_mvuwizVtgxbHsd1vh76xU7UH9_jHxWRkpoqQ5pdHB44-LjK5e15DgJ22sNs1HV0ouVNzDdLhdrvSj2_n8m_QEUf9xf-vQvTrHyx-KkatiFcDq2OxnFsQlikoMVvvYiOpsOumwemjCPVMThwF86vQ_PJ0E_PioOj9qnnBCqDF5xvPPGQMkAR_J1DVCg3uxd5u6-Npb0PHpfCvhPvrAHq44P_EvEhZge8WxWaAqdfOxgT9pCyCGol8kDoAz0jFmQ",
"refresh_token": "Np4qZKiC1-ChAeA6KwclIpEd72frn6afBj6KyrFGEIDeKtVCzerUIqTs1uwAWdrbhW1qXg7Qxx19pmIkLbHuKlSROToWOO5GCPC_Jf44NysVeyzlD8bfnRtyDMrAHFuT",
"scope": "oa",
"token_type": "Bearer",
"expires_in": 3584
}
b)失败返回示例如下:
{
"error_description": "client_id不正确",
"error_code": "100031",
"error_uri": "https://esp.xkw.cn/doc/error?q=error_code"
}
企业服务平台和接入的企业内部应用系统的接口请求,均可通过access_token来获取成员的身份信息。
这里就要使用到时返回的access_token,解析后内容如下:
以上access_token中的sub就是用户ID,接口调用方不需要验证,如果需要调用企业服务开放接口或企业内部应用系统时,由对接的应用系统(接口提供方,详情查看“开放接口”说明文档)在接收到请求时,使用平台公钥进行验证;
以上内容解析出来,scope值仅仅是oa,只是一个例子,可以为空,目前企业服务平台仅认证,不授权。后续升级使用会统一通知。
接口返回access_token有效期为expires_in,单位是秒,调用方要做好token的缓存处理,
xxxxxxxxxx
缓存时间 = expires_in - 60 * 10
缓存时间只要将平台返回的expires_in减去10分钟即可。
注意:不要频繁请求获取access_token,以免被限流控制;
在http请求的header部分,增加以下内容,key为Authorization,value为"Bearer " + access_token值
key | Value |
---|---|
Authorization | Bearer eyJraWQiOiJjM2Q2ZDAxYiIsInR5cCI6IkpXVCIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiJ4eTA3NjE5IiwiYXVkIjoiZGV2aWNlIiwibmJmIjoxNzE3ODQwNDM0LCJzY29wZSI6WyJvYSJdLCJpc3MiOiJodHRwczovL2VzcDIuZG9jLnhrdy5jbiIsImV4cCI6MTcxNzg0NDAzNCwiaWF0IjoxNzE3ODQwNDM0fQ.H-8COli2z-SmOwmdGII2qEOrg8tNygECB_LgO9ilQD2HguhLo310tvFzCUdoXVmcn1QBbs_JFjYr2DwEkvtgz9r_mvuwizVtgxbHsd1vh76xU7UH9_jHxWRkpoqQ5pdHB44-LjK5e15DgJ22sNs1HV0ouVNzDdLhdrvSj2_n8m_QEUf9xf-vQvTrHyx-KkatiFcDq2OxnFsQlikoMVvvYiOpsOumwemjCPVMThwF86vQ_PJ0E_PioOj9qnnBCqDF5xvPPGQMkAR_J1DVCg3uxd5u6-Npb0PHpfCvhPvrAHq44P_EvEhZge8WxWaAqdfOxgT9pCyCGol8kDoAz0jFmQ |