2FA NODE (英语:
该库生成并验证基于时间的一次性密码(TOTP,RFC 6238)和基于HMAC的一次性密码(HOTP,RFC 4226),用于双因子认证(2FA). 也创造了秘密 otpauth:// URI和认证器应用的QR代码如Google认证器或Authy扫描.
特征
- 生成 2FA 秘密:一个随机基数32,其
otpauth://URI和那个URI的QR代码. - 生成和校验 TOTP 令牌:6位码每30秒更改一次,可选择只接受每个令牌一次.
- 生成并验证 HOTP 令牌6位码绑在柜台上.
安装
npm install 2fa-node
需要节点20.19或以后.
使用量
生成 TOTP 秘密
import { generateSecret } from "2fa-node";
const { secret, uri, qr } = await generateSecret({
name: "MyApp", // issuer shown in the authenticator app
account: "[email protected]", // account shown in the authenticator app
});
console.log(secret); // store it for the user
console.log(uri); // otpauth://totp/MyApp:user%40example.com?secret=...&issuer=MyApp
console.log(qr); // PNG data URL to show to the user
生成 HOTP 秘密
import { generateSecret } from "2fa-node";
const { secret, uri, qr } = await generateSecret(
{ name: "MyApp", account: "[email protected]", counter: 0 },
"HOTP",
);
校验 TOTP 令牌
import { verifyToken } from "2fa-node";
const secret = "JBSWY3DPEHPK3PXP"; // the user's stored secret
const token = "123456"; // the token typed by the user
const isValid = verifyToken(secret, token);
console.log(isValid); // true if valid, false otherwise
只接受一次每个 TOTP 令牌
import { verifyTokenOnce } from "2fa-node";
const secret = "JBSWY3DPEHPK3PXP"; // the user's stored secret
const token = "123456"; // the token typed by the user
const lastTimeStep = null; // the user's stored time step, null before the first login
const match = verifyTokenOnce(secret, token, lastTimeStep);
if (match) {
// Save match.timeStep as the user's lastTimeStep, so this token cannot be used again.
}
生成 TOTP 令牌
import { generateToken } from "2fa-node";
const secret = "JBSWY3DPEHPK3PXP";
const result = generateToken(secret);
console.log(result?.token); // the current token, or undefined if the secret is invalid
验证 HOTP 令牌
import { verifyHOTPToken } from "2fa-node";
const secret = "JBSWY3DPEHPK3PXP"; // the user's stored secret
const token = "123456"; // the token typed by the user
const counter = 1; // the user's stored counter
const isValid = verifyHOTPToken(secret, token, counter);
if (isValid) {
// Save counter + 1 so this token cannot be used again.
}
生成 HOTP 令牌
import { generateHOTPToken } from "2fa-node";
const secret = "JBSWY3DPEHPK3PXP";
const counter = 1;
const result = generateHOTPToken(secret, counter);
console.log(result?.token); // the token, or undefined if the secret is invalid
API 文档
托肯斯有6位数字,并使用HMAC-SHA1;TOTP令牌每30秒改变一次. 秘密是至少80个比特(16个字符)的大小写不敏感的基础32字符串.
generateSecret(options: SecretOptions, type: OtpType = "TOTP"): Promise<{ secret: string; uri: string; qr: string }>
生成二因子认证的随机密钥 .
- 参数数字 :
options.name: 认证器应用中显示的发行者,通常是您的产品名.options.account:在认证程序app中显示的账户,通常是用户的电子邮件.options.counter(可选):写给URI的初始HOTP计数器. 默认为0;为TOTP忽略.options.numberOfSecretBytes(可选的):以字节表示的秘密大小. 默认为20; 必须是至少是一个整数16,因为RFC 4226需要128位密钥.type数字 :"TOTP"(违约)或"HOTP"。 。 。 .
- 回返:承诺决心:
secret: base32 为用户存储的密件.uri页:1otpauth://URI (英语).qr:一个URI的QR代码的PNG数据URL.
- 掷出数字 :
TypeError用于未知的type· ;RangeError无效numberOfSecretBytes或 HOTP 语言counter。 。 。 .
generateToken(secret: string): { token: string } | null
生成当前 TOTP 令牌 .
- 回返数字 :
{ token },或null如果这个秘密无效.
verifyToken(secret: string, token?: string, window: number | [number, number] = 1): boolean
验证一个 TOTP 符号 .
- 参数数字 :
window:现在前后的30秒步被接受. 使用[past, future]不同价值;0只接受当前步骤.
- 回返数字 :
true如果该标志有效;false否则,包括当该令牌丢失或变形或该秘密无效时. - 掷出数字 :
RangeError若为window并非由非负整数所制成,或跨度超过总共98个步骤.
verifyTokenOnce(secret: string, token?: string, lastTimeStep?: number | null, window: number | [number, number] = 1): { timeStep: number } | null
验证像 TOTP 等的标志 verifyToken,但也拒绝从 lastTimeStep 或更早,所以每个令牌只接受一次.
- 参数数字 :
lastTimeStep页:1timeStep由用户上次成功检查返回,或null编号 :undefined如果没有.window: 与单位相同verifyToken。 。 。 .
- 回返数字 :
{ timeStep }以符号所属的30秒步骤表示,或null如果该标志被拒绝。 保存timeStep每次成功后为用户. - 掷出: 与
verifyToken外加一个RangeError若为lastTimeStep不是一个非负式安全整数.
generateHOTPToken(secret: string, counter: number = 0): { token: string } | null
生成一个计数器的 HOTP 符号 .
- 回返数字 :
{ token },或null如果这个秘密无效. - 掷出数字 :
RangeError若为counter不是一个非负式安全整数.
verifyHOTPToken(secret: string, token: string | undefined, counter: number): boolean
核实一个HOTP的标志 与特定的计数器对齐.
- 回返数字 :
true如果该标志有效;false否则,包括当该令牌丢失或变形或该秘密无效时. - 掷出数字 :
RangeError若为counter不是一个非负式安全整数.
类型
SecretOptions 财务报告和审定财务报表 OtpType (单位:千美元)"TOTP" | "HOTP")为 TypeScript 用户导出.
安全说明
-
verifyToken在窗口内时再次接受相同的同物。 屏蔽重放, 使用verifyTokenOnce,包括确认入学的支票,并保存返回的timeStep只有它向前移动。 在单个语句中做到这一点,并将零更新行作为失败的登录处理,因此两个具有同义的同步请求不能同时成功:UPDATE users SET last_time_step = $step WHERE id = $id AND (last_time_step IS NULL OR last_time_step < $step);对HOTP来说,同样推进计数器:
UPDATE users SET counter = counter + 1 WHERE id = $id AND counter = $counter。 。 。 . -
限制用户可以做多少次验证尝试 .
-
保持保密 休息.
从 0.x 升级
- HOTP令牌现在跟随RFC 4226并匹配认证器应用,因此它们与所出自0.x的令牌不同.
verifyToken财务报告和审定财务报表verifyHOTPToken返回时false改为null当它不见了.verifyToken默认接受前后的一步(30秒),而不是四步.verifyHOTPToken需要的计数器 不再使用window论点,从未产生任何效果.- 秘密必须是至少80个比特的犬类基础32. 0.x接受的秘密,比如有空间的秘密,额外
=padding 或非 0 未使用的后导位, 现在让生成函数返回null函数返回false。 。 。 . numberOfSecretBytes必须是至少16。无效类型、计数器和窗口.- URI带标准
issuer参数代替name。 。 。 . - 只有包入口才能被导入:深入口,例如
2fa-node/dist/secret.js没有工作. - 需要20.19节节点或以后.
- 许可证由MIT改为MPL-2.0.
依赖关系
许可证
该项目根据Mozilla公共许可证2.0获得许可——见 利比里亚 详细文件.