# webauthn-browser
**Repository Path**: OpenFlun/webauthn-browser
## Basic Information
- **Project Name**: webauthn-browser
- **Description**: WebAuthn 前端库,提供简单易用的接口来处理 WebAuthn 认证流程,支持 Passkeys 和 FIDO2 标准;
- **Primary Language**: Unknown
- **License**: ISC
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-11-02
- **Last Updated**: 2026-11-11
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# @flun/webauthn-browser

[![npm (scoped)][npm-badge]][npm-link]
## 简介
**@flun/webauthn-browser** 是一个专为浏览器环境设计的 WebAuthn(含 Passkeys)前端工具库,
基于 [@simplewebauthn/browser](https://simplewebauthn.dev/) 核心逻辑重构并增强,它封装了 `navigator.credentials` API
的复杂细节,提供简洁的 Promise 风格接口,并内置了丰富的错误处理与 Base64URL 编解码工具,
并且新增在Windows下优先调用底层Windows hello 注册/认证(避免环境干扰与安全);
本包以 **ESM** 编写,同时提供 **UMD** 打包产物,可通过 npm 模块方式或 `
```
*** 注意 ES5(不再支持)***
---
## 函数方式
### 核心认证方法
#### startRegistration(options)
发起 WebAuthn 注册流程,创建新凭证;
**参数**
| 字段名 | 类型 | 默认值 | 描述 |
| ----------------- | --------- | ------- | ------------------------------------------------------------- |
| `optionsJSON` | `object` | 必填 | 由服务端调用 `generateRegistrationOptions()` 生成的 JSON 对象 |
| `useAutoRegister` | `boolean` | `false` | 是否启用条件媒介自动注册(实验性,需浏览器支持 Conditional UI) |
**返回值** `Promise`
返回一个经过标准化处理的 JSON 对象,可直接发送给后端 `verifyRegistrationResponse()` 验证;响应格式如下:
```ts
interface RegistrationResponseJSON {
id: string;
rawId: string;
response: {
attestationObject: string;
clientDataJSON: string;
transports?: AuthenticatorTransport[];
publicKeyAlgorithm?: number;
publicKey?: string;
authenticatorData?: string;
};
type: string;
clientExtensionResults: AuthenticationExtensionsClientOutputs;
authenticatorAttachment?: string;
}
```
**示例**
```js
const response = await startRegistration({ optionsJSON });
// 发送 response 至服务端
```
#### startAuthentication(options)
发起 WebAuthn 认证(登录)流程;
**参数**
- `optionsJSON`
- 类型:`object`
- 默认值:必填
- 描述:由服务端调用 `generateAuthenticationOptions()` 生成的 JSON 对象
- `useBrowserAutofill`
- 类型:`boolean`
- 默认值:`false`
- 描述:是否启用条件媒介(自动填充),实现无感登录
- `verifyBrowserAutofillInput`
- 类型:`boolean`
- 默认值:`true`
- 描述:启用自动填充时是否检查页面是否存在 `autocomplete="... webauthn"` 的 input 元素
**返回值** `Promise`
```ts
interface AuthenticationResponseJSON {
id: string;
rawId: string;
response: {
authenticatorData: string;
clientDataJSON: string;
signature: string;
userHandle?: string;
};
type: string;
clientExtensionResults: AuthenticationExtensionsClientOutputs;
authenticatorAttachment?: string;
}
```
**示例**
```js
// 普通登录
const response = await startAuthentication({ optionsJSON });
// 自动填充登录(需页面存在 )
const response = await startAuthentication({
optionsJSON,
useBrowserAutofill: true
});
```
### 环境检测方法
#### browserSupportsWebAuthn()
检查当前浏览器是否支持 WebAuthn API;
**返回值** `boolean`
```js
if (flunWebAuthnBrowser.browserSupportsWebAuthn()) {
// 可以使用 WebAuthn
}
```
#### platformAuthenticatorIsAvailable()
检查平台认证器(如 Touch ID、Face ID、Windows Hello)是否可用;
**返回值** `Promise`
```js
const available = await flunWebAuthnBrowser.platformAuthenticatorIsAvailable();
```
#### browserSupportsWebAuthnAutofill()
检查当前浏览器是否支持 WebAuthn 条件媒介(自动填充);
**返回值** `Promise`
```js
if (await flunWebAuthnBrowser.browserSupportsWebAuthnAutofill()) {
// 可以使用 useBrowserAutofill 选项
}
```
### 编解码工具
这些工具函数直接挂载在导出对象上,便于前后端统一数据格式;
| 函数 | 描述 |
| ---------------------------------------------- | -------------------------------------- |
| `bufferToBase64URLString(buffer: ArrayBuffer)` | 将 ArrayBuffer 转换为 Base64URL 字符串 |
| `base64URLStringToBuffer(base64url: string)` | 将 Base64URL 字符串转换为 ArrayBuffer |
**示例**
```js
const { bufferToBase64URLString, base64URLStringToBuffer } = flunWebAuthnBrowser,
challengeBuffer = base64URLStringToBuffer(optionsJSON.challenge),
encoded = bufferToBase64URLString(challengeBuffer);
```
### 错误类与中止服务
#### WebAuthnError
自定义错误类,继承自 `Error`;当认证/注册过程中发生可识别的错误时抛出;
**属性**
| 属性 | 类型 | 描述 |
| ------- | -------- | -------------------------- |
| `name` | `string` | 错误名称(通常为原始错误名) |
| `code` | `string` | 标准化的错误码(见下方表格) |
| `cause` | `Error` | 浏览器抛出的原始错误对象 |
**常见错误码**
| 错误码 | 描述 |
| ------------------------------------------------------------- | ---------------------------------------------- |
| `ERROR_CEREMONY_ABORTED` | 认证/注册流程被中止(如调用 `cancelCeremony()`) |
| `ERROR_INVALID_DOMAIN` | 当前域名无效 |
| `ERROR_INVALID_RP_ID` | RP ID 与当前域名不匹配 |
| `ERROR_AUTHENTICATOR_GENERAL_ERROR` | 认证器通用错误 |
| `ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED` | 认证器已被注册(注册时) |
| `ERROR_AUTHENTICATOR_MISSING_DISCOVERABLE_CREDENTIAL_SUPPORT` | 需要可发现凭证但认证器不支持 |
| `ERROR_PASSTHROUGH_SEE_CAUSE_PROPERTY` | 透传错误,需查看 `cause` 属性 |
#### WebAuthnAbortService
用于手动取消正在进行的 WebAuthn 操作;
**方法**
| 方法 | 描述 |
| ------------------------ | ----------------------------------------- |
| `createNewAbortSignal()` | 创建新的 AbortSignal,并自动中止之前的操作 |
| `cancelCeremony()` | 主动取消当前正在进行的认证/注册流程 |
```js
// 取消当前所有 WebAuthn 操作
flunWebAuthnBrowser.WebAuthnAbortService.cancelCeremony();
```
### 内部调试工具
以下属性暴露了部分内部实现细节,**仅用于高级调试或扩展,不推荐在生产中直接使用**;
| 属性 | 描述 |
| ------------------------------------------- | ---------------------- |
| `_browserSupportsWebAuthnInternals` | 内部检测函数的桩对象 |
| `_browserSupportsWebAuthnAutofillInternals` | 自动填充检测的内部实现 |
### 使用示例
以下示例演示了最基本的调用方式,默认与后端使用 JSON 交互;
#### 模块方式
```js
import { startRegistration, startAuthentication } from '@flun/webauthn-browser';
// 注册
async function register(username) {
const regOptions = await fetch('/api/register/begin', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username })
}).then(r => r.json());
const regResponse = await startRegistration({ optionsJSON: regOptions });
await fetch('/api/register/complete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, response: regResponse })
});
}
// 登录
async function login(username) {
const authOptions = await fetch('/api/login/begin', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username })
}).then(r => r.json());
const authResponse = await startAuthentication({ optionsJSON: authOptions }),
verifyRes = await fetch('/api/login/complete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, response: authResponse })
});
return verifyRes.json();
}
```
#### 全局方式
在 HTML 页面中引入 UMD 脚本后,即可通过全局变量 `flunWebAuthnBrowser` 调用所有方法;
```html
```
### 集成示例
#### 配合 @flun/webauthn-server
以下是一个完整的最小化集成示例,前端使用本库,
后端使用 [`@flun/webauthn-server`](https://www.npmjs.com/package/@flun/webauthn-server);
**前端代码**
```js
import { startRegistration, startAuthentication, browserSupportsWebAuthn} from '@flun/webauthn-browser';
async function register(username) {
// 1. 请求注册选项
const optionsRes = await fetch('/api/register/begin', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username })
}), options = await optionsRes.json(),
// 2. 启动浏览器注册流程
response = await startRegistration({ optionsJSON: options }),
// 3. 将响应发送给服务端验证
verifyRes = await fetch('/api/register/complete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, response })
});
return verifyRes.json();
}
async function login(username) {
// 1. 请求认证选项
const optionsRes = await fetch('/api/login/begin', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username })
}), options = await optionsRes.json(),
// 2. 启动浏览器认证流程(可开启自动填充)
response = await startAuthentication({ optionsJSON: options }),
// 3. 发送响应验证
verifyRes = await fetch('/api/login/complete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, response })
});
return verifyRes.json();
}
```
**后端代码片段**(基于 Express + `@flun/webauthn-server`)
```js
import {
generateRegistrationOptions, verifyRegistrationResponse, generateAuthenticationOptions, verifyAuthenticationResponse
} from '@flun/webauthn-server';
app.post('/api/register/begin', async (req, res) => {
const { username } = req.body, user = getUser(username),
options = await generateRegistrationOptions({
rpName: 'My App',
rpID: 'localhost',
userName: username,
userID: user.id,
});
storeChallenge(username, options.challenge);
res.json(options);
});
app.post('/api/register/complete', async (req, res) => {
const { username, response } = req.body, expectedChallenge = getChallenge(username),
verification = await verifyRegistrationResponse({
response,
expectedChallenge,
expectedOrigin: 'http://localhost:7296',
expectedRPID: 'localhost',
});
if (verification.verified) {
saveCredential(username, verification.registrationInfo);
res.json({ success: true });
} else {
res.status(400).json({ error: 'Verification failed' });
}
});
// 认证接口类似...
```
---
## 常见问题
推荐使用 `try...catch` 捕获 `WebAuthnError` 并根据 `code` 进行差异化处理;
```js
import { startAuthentication, WebAuthnError } from '@flun/webauthn-browser';
try {
const response = await startAuthentication({ optionsJSON });
// 发送 response
} catch (err) {
if (err instanceof WebAuthnError) {
switch (err.code) {
case 'ERROR_CEREMONY_ABORTED':
console.log('用户取消了操作');
break;
case 'ERROR_INVALID_RP_ID':
alert('配置错误:RP ID 无效');
break;
default:
console.error('认证失败', err.message);
}
} else {
// 处理其他非 WebAuthn 错误
}
}
```
---
## 许可证
ISC © [flun](https://github.com/OpenFlun)
---
## 贡献
- [GitHub 仓库](https://github.com/OpenFlun/webauthn-browser)
- [gitee 仓库](https://gitee.com/OpenFlun/webauthn-browser)
- [npm 包页面](https://www.npmjs.com/package/@flun/webauthn-browser)
- [配套后端库 @flun/webauthn-server](https://www.npmjs.com/package/@flun/webauthn-server)
- [W3C WebAuthn 规范](https://w3c.github.io/webauthn/)
[npm-badge]: https://img.shields.io/npm/v/@flun/webauthn-browser?style=for-the-badge&logo=npm
[npm-link]: https://www.npmjs.com/package/@flun/webauthn-browser