跳转到内容

设备码模式

有些客户端所在的环境是没有浏览器的。例如:COZE(扣子)、智能电视、媒体控制台、数字相框、打印机等,像这类的设备,要在设备上将用户操作引导至认证平台界面去扫码登录,或者输入账号和密码,然后确认授权,这显然不现实。解决这类设备的登录场景,最常见的就是手机扫码登录,或将认证地址发送到手机上,让用户在手机浏览器上进行认证授权。在 OAuth 2.1 中,已经加入设备授权码模式,那么本篇就来实现一下设备授权码登录。

用户在COZE(扣子)进行公司用户的认证授权流程,如果没有认证,就会输出消息,引导点击链接或者生成二维码进行扫码,完成认证就可以开始后续的对话联系了。

coze

OAuth2.1的设计背景,在于允许用户在不告知第三方自己的账号密码情况下,通过授权方式,让第三方服务可以获取自己的资源信息。 详细的协议介绍,开发者可以参考The OAuth 2.1 Authorization Framework,以及OpenID Connect Core 1.0 incorporating errata set 2

device-login

以上图交互比较多,但是对于设备终端来说,只要关注两个步骤:

1、图中步骤1,获取设备码;

2、图中步骤5,轮询请求,间隔5秒,获取access_token;

其他所有交互,企业服务平台已经实现,设备终端不需要关注。

请求方式: POST(HTTPS) Content-Type: application/x-www-form-urlencoded

请求地址: /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) 成功返回示例如下:

{
"user_code": "QWFN-VTLP",
"device_code": "sf1NvQqp3A5kmSzfTW30UwrIlz_Ey4cFyomduHY8VtOZkQ3CnYsnwAwZROiJEpxr8tIEMJ4WDgC4rookrJCZ732KEmErF6UujpiI4_eBRDFXmWH3hQpGg-FdkDwPkRCw",
"verification_uri_complete": "https://uat-esp.xkw.cn/oauth2/device_verification?user_code=QWFN-VTLP",
"verification_uri": "https://uat-esp.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的缓存处理,

缓存时间 = expires_in - 60

缓存时间只要将平台返回的expires_in减去1分钟即可。

注意:不要频繁请求获取device_code,以免被限流控制;

注意:间隔2~3秒,比如5秒,间隔时间不要太短,没有必要,用户的交互需要一定的时间。

请求方式: POST(HTTPS) Content-Type: application/x-www-form-urlencoded

请求地址: /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_typetoken类型
expires_inaccess_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,解析后内容如下:

image-20240608190851439

以上access_token中的sub就是用户ID,接口调用方不需要验证,如果需要调用企业服务开放接口或企业内部应用系统时,由对接的应用系统(接口提供方,详情查看“开放接口”说明文档)在接收到请求时,使用平台公钥进行验证;

以上内容解析出来,scope值仅仅是oa,只是一个例子,可以为空,目前企业服务平台仅认证,不授权。后续升级使用会统一通知。

接口返回access_token有效期为expires_in,单位是秒,调用方要做好token的缓存处理,

缓存时间 = expires_in - 60 * 10

缓存时间只要将平台返回的expires_in减去10分钟即可。

注意:不要频繁请求获取access_token,以免被限流控制;

在http请求的header部分,增加以下内容,key为Authorization,value为”Bearer ” + access_token值

keyValue
AuthorizationBearer eyJraWQiOiJjM2Q2ZDAxYiIsInR5cCI6IkpXVCIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiJ4eTA3NjE5IiwiYXVkIjoiZGV2aWNlIiwibmJmIjoxNzE3ODQwNDM0LCJzY29wZSI6WyJvYSJdLCJpc3MiOiJodHRwczovL2VzcDIuZG9jLnhrdy5jbiIsImV4cCI6MTcxNzg0NDAzNCwiaWF0IjoxNzE3ODQwNDM0fQ.H-8COli2z-SmOwmdGII2qEOrg8tNygECB_LgO9ilQD2HguhLo310tvFzCUdoXVmcn1QBbs_JFjYr2DwEkvtgz9r_mvuwizVtgxbHsd1vh76xU7UH9_jHxWRkpoqQ5pdHB44-LjK5e15DgJ22sNs1HV0ouVNzDdLhdrvSj2_n8m_QEUf9xf-vQvTrHyx-KkatiFcDq2OxnFsQlikoMVvvYiOpsOumwemjCPVMThwF86vQ_PJ0E_PioOj9qnnBCqDF5xvPPGQMkAR_J1DVCg3uxd5u6-Npb0PHpfCvhPvrAHq44P_EvEhZge8WxWaAqdfOxgT9pCyCGol8kDoAz0jFmQ