FIDO Server
此模块包含 FIDO Server 对接的相关接口,用于提供 Web 服务器快速支持 WebAuthn 认证的能力。
首先,在 WebAuthn 的注册和认证过程中。每个过程均需要调用两个接口,我们称为 xxxOptions
和 xxxResult
。
xxxOptions
是获取本次操作的挑战,称为challenge
。xxxResult
是应对改挑战产生的结果
就比如,一个登录过程是这样的:
- 首先,输入用户名,点击 WebAuthn 登录。
- 前端会通过
xxxOptions
获取challenge
- 前端将获取到的
challenge
调用浏览器接口credential.create()
- 浏览器弹出 WebAuthn 认证窗口
- 认证器得到相关的提示,进行认证,返回认证结果
- 前端将认证结果通过
xxxResult
提交到后端 - 后端调用 FIDO Server 接口进行确认
- 后端返回结果到前端,结束
这里用伪代码形式示例调用过程。
创建客户端
import (
"github.com/trustasia-com/go-sdk/pkg/credentials"
"github.com/trustasia-com/go-sdk/webauthn"
)
opts := credentials.Options {
AccessKey: "accessKey",
SecretKey: "secretKey",
Endpoint: "https://api.wekey.com",
SignerType: credentials.SignatureDefault,
}
// sess会自动处理签名
sess, err := credentials.New(opts, false)
if err != nil {
return err
}
webauthnCli := webauthn.New(sess)
添加注册接口
func handleAttestationOptions(w http.ResponseWriter, r *http.Request) {
// 通过某种方式查询到用户ID,如从cookie里获取到的
userID := "..." or username := "..."
// 查询到用户
user := selectUser(userID)
// 将 userID 进行 hex 编码
uid := hex.EncodeToString(userID)
// 构建注册请求
req := webauthn.StartSignUpReq {
Username: user.Username,
DisplayName: user.Nickname,
// ...
}
// 调用 SDK 方法
data, err := webauthnCli.StartSignUp(req, uid)
if err != nil {
// 打印日志
log.Error(err)
// TODO 错误处理
return
}
// 成功,返回合适格式将data带回去
w.WriteHeader(200)
w.Write(data)
}
func handleAttestationResult(w http.ResponseWriter, r *http.Request) {
// 从body里读区data
data, err := io.ReadAll(r.Body)
if err != nil {
// TODO 错误处理
return
}
// 调用 SDK 接口
data, err := webauthnCli.FinishSignUp(r)
if err != nil {
// TODO 错误处理
return
}
// 将结果返回
w.WriteHeader(200)
w.Write(data)
}
添加认证接口
func handleAssertionOptions(w http.ResponseWriter, r *http.Request) {
// 比如登录时传过来的username
user := selectUserByUsername(username)
req := webauthn.StartSignInReq{
Username: user.Username,
DisplayName: user.Nickname,
// ...
}
// 将userID hex编码
uid := hex.EncodeToString(user.ID)
data, err := webuathnCli.StartSignIn(req, uid)
if err != nil {
// TODO 错误处理
return
}
// 返回数据
w.WriteHeader(200)
w.Write(data)
}
func handleAssertionResult(w http.ResponseWriter, r *http.Request) {
data, err := webauthnCli.FinishSignIn(r)
if err != nil {
// TODO 错误处理
return
}
// 数据返回
w.WriteHeader(200)
w.Write(data)
}
具体demo请参考这里:WebAuthn Demo