Fido扫码认证
FIDO扫码认证
FIDO扫码认证解决了什么问题?我们知道FIDO2的组成:WebAuthn+CTAP。其中CTAP规范了WebAuthn数据如何到达FIDO认证器端。但就目前比较通用的形势有:
- BLE
- NFC
- USB
这几种方式有什么问题:
- 需要设备支持,但不一定每个设备都有NFC或者BLE
- 基于USB的FIDO设备,一般是硬件形态,容易丢失,硬件漏洞难以修复
- BLE协议被发现不够安全,Apple、Google等浏览器和平台都不支持
- iOS与Android手机系统有平台限制,不能够很好的跨平台
那么WeKey做了什么?WeKey同样是基于FIDO2标准。实现了标准的认证器与FIDO Server。为了支持FIDO扫码认证,同样WeKey实现了标准FIDO Client。
架构设计
我们这里将需要对接扫码认证的服务称为RP。WeKey提供后台控制台供客户为RP创建密钥用于对接。当RP接入到WeKey认证系统,即可以快速支持基于FIDO的扫码认证。
开始对接
所有接口均采用 签名机制 进行鉴权,后续不再赘述,建议通过 SDK 进行对接。
后端整个过程对接需要涉及到两个过程:
- 注册凭证
- 预注册
- 注册
- 验证凭证
- 预认证
- 认证
接口调用Host:https://api.wekey.com/ta-app
注册凭证
凭证的注册意味凭证的存储,WeKey提供两种存储方式:用户的手机或HSM云存储,
当用户选择将凭证存储在自己的手机中时,凭证的所有信息,WeKey将不会获取,凭证信息将会存储在用户手机的专用安全芯片中,同时也意味着用户更换设备登录, 将无法使用该凭证进行认证操作。
当用户选择HSM云存储时,WeKey会将凭证的信息存储存储在HSM服务中,同样地,在专业的云HSM存储下,WeKey无法获取用户凭证的私钥信息,用户更换设备后, 依旧可以同步并使用该凭证,选用云HSM方式存储凭证既安全又便捷,WeKey推荐您优先选择HSM。
流程如下:
简述:
- 用户发起注册凭证的请求,RP根据用户信息向WeKey发起预注册凭证的请求
- WeKey将响应RP消息地址和该次请求的过期时间,以便RP处理逻辑
- RP将消息地址转化为二维码展示,同时开始根据过期时间获取认证结果
- 用户使用WeKey的APP在RP处进行扫码,获取认证的信息
- 用户在APP上完成授权,同时上传结果至WeKey
- WeKey响应RP认证的结果
预注册
获取用于APP扫描的二维码信息。
调用方式:POST,调用地址:/rp/attestation/options
请求参数(body):
字段 | 类型 | 选项 | 说明 |
---|---|---|---|
user_id | string | 必填 | 用户id,需要在您系统内可以唯一标识该用户的 |
username | string | 必填 | 用户名 |
credential_name | string | 可选 | 创建的凭证名字,不填则由WeKey随机生成,建议填写,方便用户标识 |
display_name | string | 可选 | 用户昵称 可选 |
响应参数:
字段 | 类型 | 说明 |
---|---|---|
url | string | 消息地址,请转化为二维码以便WeKey APP扫码 |
expires_at | int | 请求过期时间,时间戳,单位秒 |
请求示例:
{
"user_id": "testuserid",
"username": "jack",
"credential_name": "my cred",
"display_name": "imjack"
}
成功响应:
{
"code": 0,
"data": {
"url": "https://get.wekey.com#0cdq8va3tlntsv8hko530",
"expires_at": 1668583416
},
"error": ""
}
注册
通过轮询接口的形式判断手机端是否认证成功。
调用方式:GET,调用地址:/rp/attestation/result?msg_id=xxx
请求参数(query):
字段 | 类型 | 选项 | 说明 |
---|---|---|---|
msg_id | string | 必填 | 消息的ID,由预注册接口返回的url解析而来,解析方式:先对url进行字符串分割(以“#”为分割),取后半部分的字符串,去除第0位即为消息的id。如: https://get.wekey.com#0cdq8va3tlntsv8hko530 解析后的msg_id即为:cdq8va3tlntsv8hko530 |
响应参数:
字段 | 类型 | 说明 |
---|---|---|
wekey_user | string | 扫码人的信息,可展示在页面方便提示用户 |
status | string | 当前认证状态,init:消息初始化,无人扫码,bind:表示已经有人扫码,此时 wekey_user有值,success:表示用户已授权, 此次认证成功,fail:表示此次认证失败 timeout:表示该次认证已超时,无人认证。请注意,success和fail状态只会出现一次,如果解析到这两种状态时,请结束轮询该接口 |
error | string | 当为fail时,该字段有值,用以告知具体的错误信息 |
示例请求:
GET https://api.wekey.com/ta-app/rp/attestation/result?msg_id=cdq8va3tlntsv8hko530
成功响应:
{
"code": 0,
"data": {
"wekey_user": "133****2345",
"status": "bind",
"error": ""
},
"error": ""
}
认证
认证即使用免密方式验证用户的身份,可选用扫码认证或推送认证的方式进行,由RP进行自主选择。
流程如下:
简述:
- 用户发起认证的请求,RP根据用户信息向WeKey发起预认证凭证的请求
- WeKey将响应RP消息地址和该次请求的过期时间,以便RP处理逻辑
- RP将消息地址转化为二维码展示,同时开始根据过期时间获取认证结果
- 用户使用WeKey的APP在RP处进行扫码,获取认证的信息
- 用户在APP上完成授权,同时上传结果至WeKey
- WeKey响应RP认证的结果
预认证
获取用于APP扫描的二维码信息或者推送到手机端。
调用方式:POST,调用地址:/rp/assertion/options
请求参数(body):
字段 | 类型 | 选项 | 说明 |
---|---|---|---|
user_id | string | 必填 | 用户id,需要在您系统内可以唯一标识该用户的 |
username | string | 必填 | 用户名 |
method | string | 必填 | 认证方式,请填qrcode或push,当值为qecode时,WeKey会返回认证的url,不会进行推送,当为push时,WeKey将会把认证请求推送到用户手机上 |
响应参数:
字段 | 类型 | 说明 |
---|---|---|
url | string | 消息地址,请转化为二维码以便WeKey APP扫码 |
expires_at | int | 请求过期时间,时间戳,单位秒 |
示例请求:
{
"user_id": "testuserid",
"username": "jack",
"method": "push"
}
成功响应:
{
"code": 0,
"data": {
"url": "https://get.wekey.com#1cdq8va3tlntsv8hko530",
"expires_at": 1668583416
},
"error": ""
}
认证
用户请求认证时,用于获取认证的结果
调用方式:GET,调用地址:/rp/assertion/result?msg_id=xxx
请求参数(query):
字段 | 类型 | 选项 | 说明 |
---|---|---|---|
id | string | 必填 | 消息的ID,由预注册接口返回的url解析而来,解析方式:先对url进行字符串分割(以“#”为分割),取后半部分的字符串,去除第0位即为消息的id。如: https://get.wekey.com#0cdq8va3tlntsv8hko530 解析后的id即为:cdq8va3tlntsv8hko530 |
响应参数:
字段 | 类型 | 说明 |
---|---|---|
wekey_user | string | 扫码人的信息,可展示在页面方便提示用户 |
status | string | 当前认证状态,init:消息初始化,无人扫码,bind:表示已经有人扫码,此时 wekey_user有值,success:表示用户已授权, 此次认证成功,fail:表示此次认证失败 timeout:表示该次认证已超时,无人认证。请注意,success和fail状态只会出现一次,如果解析到这两种状态时,请结束轮询该接口 |
user_id | string | 如果认证成功,该字段会有值,为注册凭证时的user id |
error | string | 当为fail时,该字段有值,用以告知具体的错误信息 |
示例请求:
GET https://api.wekey.com/ta-app//rp/assertion/result?msg_id=cdq8va3tlntsv8hko530
成功响应:
{
"code": 0,
"data": {
"wekey_user": "133****2345",
"status": "success",
"error": "",
"user_id": "jack"
},
"error": ""
}
查询凭证
查询凭证,用于RP处显示用户注册过的凭证
调用方式:GET,调用地址:/rp/credentials
请求参数(query):
字段 | 类型 | 选项 | 说明 |
---|---|---|---|
user_id | string | 必填 | query参数,用户id,需要在您系统内可以唯一标识该用户的 |
响应参数:
字段 | 类型 | 说明 |
---|---|---|
credential_id | string | 凭证id,删除凭证时可用 |
credential_name | string | 凭证名,创建时填写的 |
user_id | string | 用户id |
created_at | string | 凭证创建时间,RFC3339格式 |
updated_at | string | 凭证最近使用时间,RFC3339格式 |
请求示例:
GET https://api.wekey.com/ta-app/rp/credentials?user_id=jack
成功响应:
{
"code":0,
"data":{
"total":1,
"list":[
{
"credential_id":"cred id",
"credential_name":"cred name",
"user_id":"jack",
"created_at":"2022-11-07T00:00:00Z",
"updated_at":"2022-11-07T00:00:00Z"
}
]
},
"error":""
}
删除凭证
用于用户删除凭证
调用方式:DELETE,调用地址:/rp/credentials
请求参数(body):
字段 | 类型 | 选项 | 说明 |
---|---|---|---|
user_id | string | 必填 | query参数,用户id,需要在您系统内可以唯一标识该用户的 |
credential_ids | []string | 必填 | 凭证id的数组,查询列表可获得 |
响应参数:
字段 | 类型 | 说明 |
---|---|---|
total | int | 删除成功的数量 |
示例请求:
{
"user_id":"testuserid",
"credential_ids":[
"cred1",
"cred2"
]
}
成功响应:
{
"code":0,
"data":{
"total":2
},
"error":""
}