共计 3798 个字符,预计需要花费 10 分钟才能阅读完成。
博客原文:https://blog.zhangbing.site/2020/12/28/what-is-webauthn-logging-in-with-touch-id-and-windows-hello-on-the-web/
对你的网站启用 TouchID 和 Windows Hello 身份验证。WebAuthn 简介:它如何工作以及如何实现。
什么是 WebAuthn?
Web Authentication API 是一个认证标准,容许网站应用内置的认证器(如 Apple TouchID 和 Windows Hello)或应用平安密钥(如 Yubikey)对用户进行认证。
它利用公钥加密技术代替明码。用户注册时,将为该帐户生成一个公钥 - 私钥对。私钥平安地存储在用户的设施中,而公钥则发送到服务器。而后,服务器能够应用私钥来要求用户的设施签订“挑战书”(challenge)以验证用户身份。
向 WebAuthn 注册
注册期间,网站通常会要求用户输出用户名和明码。通过 WebAuthn,网站会生成一对公钥和私钥,将公钥发送给服务器,并将私钥平安地存储在用户的设施中。
应用 WebAuthn 登录
登录期间,网站通常会检查用户是否提供了正确的用户名和明码。借助 WebAuthn,网站将发送挑战书并查看浏览器是否能够应用存储在用户设施中的私钥对询问进行签名。
纯 JavaScript 实现
要理解更多对于 WebAuthn 的信息,这里有一个对于如何用纯 JavaScript 实现 WebAuthn 的深刻解释。请看苹果在 WWDC20 上的指南。
注册
步骤 1:你的站点申请服务器注册 WebAuthn。
要求用户输出一些标识符(用户名、电子邮件等)。而后,向你的服务器发送申请,注册一个新的 WebAuthn 凭证。
步骤 2:服务器指定一些选项来创立新的密钥对。
服务器指定了一个 PublicKeyCredentialCreationOptions
对象,该对象蕴含了创立一个新的 PublicKeyCredential
(密钥对)所需的和可选的一些字段。
const optionsFromServer = {
"challenge": "random_string", // 须要转换为 ArrayBuffer
"rp": { // 我的网站信息
"name": "My Website",
"id": "mywebsite.com"
},
"user": { // 用户信息
"name": "anthony@email.com",
"displayName": "Anthony",
"id": "USER_ID_12345678910" // 须要转换为 ArrayBuffer
},
"pubKeyCredParams": [
{
"type": "public-key",
"alg": -7 // 承受的算法
}
],
"authenticatorSelection": {authenticatorAttachment: "platform",},
"timeout": 60000 // 以毫秒为单位
};
rp
:指定依赖方的信息,用户注册 / 登录的网站。如果用户注册的是你的网站,那么你的网站就是依赖方。id
:主机的域名,不含协定和端口。例如,如果 RP 的起源是 https://login.example.com:1337,那么id
就是login.example.com
或example.com
,而不是m.login.example.com
。pubKeyCredParams
: 服务器可承受哪些公钥类型。alg
: 一个数字,形容服务器承受的算法,并在 COSE 注册表中 COSE 算法 下进行了形容。例如,- 7 用于 ES256 算法。authenticatorSelection
: (可选)限度验证器为平台或跨平台。应用platform
容许像 Windows Hello 或 TouchID 这样的身份验证器。应用cross-platform
容许身份验证器,如 Yubikey。
步骤 3:在前端,应用选项创立新的密钥对。
应用 creationOptions
咱们能够通知浏览器生成一个新的密钥对。
// 请确保你曾经将字符串转换为 ArrayBuffer
// 如上所述
const credential = await navigator.credentials.create({publicKey: optionsFromServer});
返回的凭据 (credential
) 将如下所示:
PublicKeyCredential {
id: 'ABCDESKa23taowh09w0eJG...',
rawId: ArrayBuffer(59),
response: AuthenticatorAttestationResponse {clientDataJSON: ArrayBuffer(121),
attestationObject: ArrayBuffer(306),
},
type: 'public-key'
}
步骤 4:将凭证 (credential) 发送到你的服务器。
首先,你可能须要将 ArrayBuffer
转换为 base64 编码的字符串或仅仅是字符串。你须要在你的服务器中对此进行解码。
依照这些标准来验证服务器中的凭证。而后,你应该存储凭证信息,容许用户应用此 WebAuthn 凭证登录。
登录
步骤 1:向服务器发送申请以登录。
这容许服务器发送你的前端须要签名的询问。
步骤 2:服务器发送挑战书和用户能够登录的 WebAuthn 凭据列表。
服务器指定一个 PublicKeyCredentialRequestOptions
对象,该对象蕴含要签订的挑战书和用户之前注册的 WebAuthn 证书列表。
const optionsFromServer = {
"challenge": "somerandomstring", // Need to convert to ArrayBuffer
"timeout": 60000,
"rpId": "mywebsite.com",
"allowCredentials": [
{
"type": "public-key",
"id": "AdPc7AjUmsefw37..." // Need to convert to ArrayBuffer
}
]
}
第 3 步:前端签订挑战书。
// make sure you've converted the strings to ArrayBuffer
// as mentioned above
const assertion = await navigator.credentials.get({publicKey: optionsFromServer});
返回的 assertion
如下所示:
PublicKeyCredential {
id: 'ABCDESKa23taowh09w0eJG...', // WebAuthn 凭证 ID
rawId: ArrayBuffer(59),
response: AuthenticatorAssertionResponse {authenticatorData: ArrayBuffer(191),
clientDataJSON: ArrayBuffer(118),
signature: ArrayBuffer(70), // 咱们须要验证的签名
userHandle: ArrayBuffer(10),
},
type: 'public-key'
}
步骤 4:将 assertion 发送到你的服务器并进行验证。
在将 ArrayBuffers 发送到服务器之前,你可能须要将其转换为字符串。依照验证 assertion 的标准进行。
当 assertion 被验证后,用户曾经胜利登录。当初你能够生成你的会话令牌或设置你的 cookie,而后返回前端。
须要思考的几件事
如果用户应用笔记本电脑的 TouchID 登录,你如何容许他们从其他人的笔记本电脑登录?
如果他们只能从本人的笔记本上登录,可能会有不好的用户体验。一个可能的办法是应用 WebAuthn 作为代替,并始终有一个后备登录办法(例如,应用魔术链接或 OTP)。
为一个账户增加多个 WebAuthn 凭证。
你可能心愿有一个“设置”页面,容许你的用户从其余设施登录 WebAuthn,例如,如果他们想从笔记本电脑和 iPad 同时登录 WebAuthn。浏览器不晓得你在服务器中为用户保留了哪些凭证,如果你的用户曾经注册了他们笔记本电脑的 WebAuthn 凭证,你须要通知浏览器,这样它就不会创立一个新的凭证。应用 PublicKeyCredentialCreationOptions
中的 excludeCredentials
。
WebAuthn 反对状况
目前,并非所有浏览器都反对 WebAuthn,但反对的浏览器越来越多。请拜访 FIDO 网站,查看反对 WebAuthn 的浏览器和平台列表。
完结
这应该涵盖应用 WebAuthn 注册和登录的基础知识,并帮忙你在网站上实现它。
如果你想实现 WebAuthn,这些文档可能会有所帮忙:
- React 疾速入门 - 应用 WebAuthn 登录:https://docs.cotter.app/quick…
- WebAuthn SDK Reference:https://docs.cotter.app/sdk-r…
参考
咱们援用了这些十分有用的文章来撰写这篇文章:
- WebAuthn Guide:https://webauthn.guide/
- WebAuthn Specs from W3C:https://w3c.github.io/webauthn/