厂商通过自有 APP 调用若琪 SDK 登录,会自动关联创建若琪账号,并为该账号绑定厂商驱动,从而实现通过若琪语音控制厂商自有设备的能力。这种接入方式需要厂商支持符合 RFC7519 的 JSON Web Token (JWT) 授权方式。
基于 JWT 的授权流程示意:
上图理解为以下步骤:
(1) 厂商 APP 调用若琪 SDK 登录,传入厂商 userId,若琪 SDK 将该用户信息提交到若琪服务器。
(2) 若琪服务器为厂商用户完成若琪账号绑定、厂商驱动绑定等一系列动作后,根据厂商 userId 和厂商分配给若琪的 appId、appSecret 进行 JWT 签名。
(3) 假设用户发起了一次设备控制请求,若琪会按照智能家居协议约定的消息格式,在请求消息的 authorization 字段中携带 JWT 签名,发送到厂商服务器。
(4) 厂商服务器接收到请求消息,通过对 JWT 签名进行解码和验证,读取 appId 和厂商 userId,发送响应消息。
厂商需要为若琪注册分配 appId 和 appSecret,若琪生成 JWT 签名需要依赖于此。
参数名 | 类型 | 注释 — | — | — appId | string | 厂商分配给若琪的 appId appSecret | string | 厂商分配给若琪的密钥
若琪通过调用 jwt.sign
方法,以 appSecret 为秘钥,对 userId 和 appId 进行签名:
jwt.sign(payload, secretOrPrivateKey)
其中,payload
参数格式为 { userId: ***, appId: *** }
,secretOrPrivateKey
参数即 appSecret,最终得到 token 串:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyMzQ1NiIsInVzZXJJZCI6IjEyMzQ1NiJ9.X3w57ExTufLxX59S_rpjd0DTV-9iPTfn6IjO7EJB1rY
当若琪发起控制请求时,消息格式为:
{
"header": {
"messageId": "5f8a426e-01e4-4cc9-8b79-65f8bd0fd8a4",
"namespace": "Rokid.Control",
"name": "Color.Set",
"payloadVersion": "v1",
"authorization": {
"type": "JWT",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjEyMzQ1NiIsInVzZXJJZCI6IjEyMzQ1NiJ9.X3w57ExTufLxX59S_rpjd0DTV-9iPTfn6IjO7EJB1rY",
}
},
"endpoint": {
"endpointId": "unique-id-for-user",
"additionalInfo": {
"key1": "value1"
},
"states": [
{
"interface": "Color",
"value": 12345,
"timeOfSample": "20180320T00:00:00.000Z"
}
]
},
"payload": {
"value": 65280
}
}
厂商服务器判定 authorization.type 为 JWT 时,调用 jwt.decode
解码 token 得到 appId 和厂商 userId,然后调用 jwt.verify
接口,验证 token 有效性并响应结果给若琪。
关于请求、响应、失败的消息结构请参考文档:
接入 JWT 签名授权需要使用 JWT 库提供的两个方法:
返回解码 token 后得到的 payload 信息,但不验证签名正确与否。
其中 secretOrPublicKey 即分配给若琪的 appSecret 秘钥。如果验证签名正确,则返回解码 token 后得到的 payload 信息。如果验证失败则报错。
具体的实现可以参考 jwt.io 提供的库。