我在使用Speakeasy OTP验证时遇到了一个奇怪的问题,OTP应在2分钟后过期。
生成令牌
var secret = speakeasy.generateSecret({length: 20}).base32;
var token = speakeasy.totp({
secret: secret.base32,
encoding: 'base32',
time:120
});
验证令牌
var verified = speakeasy.totp.verify({
secret:req.params.secret,
encoding: 'base32',
token: req.params.token,
time:120
});
console.log(verified);
案例1固定密钥
当我将secret
密钥更改为固定密钥(即secret='676FGFG!@$#'
)时,OTP永远不会过期console.log(已验证);始终返回false
case-2使用base32生成密钥
当我使用base32生成secret
时(即secret = secret.base32
)OTP未经验证
的console.log(认证);始终返回true
答案 0 :(得分:2)
一个问题是您的秘密实际设置为undefined
:
var secret = speakeasy.generateSecret({length: 20}).base32;
^^^^^^^ notice this
var token = speakeasy.totp({
secret: secret.base32,
^^^^^^^ and again here
后者应该是secret : secret
,因为secret
变量已经包含了秘密的Base-32字符串。
其次,time
并非用于设置到期/期限,而是step
的用途。
由于TOTP在特定时间窗口中有效,因此您不能(AFAIK)将它们设置为有效,直到"从现在开始到5未来几分钟" 。你可以做的是调整window
值,以便在验证期间允许宽容,在那里你可以说出属于"属于的标记。到5分钟前到5分钟之间的时间戳也是有效的:
// creating the token
let token = speakeasy.totp({
...
window : 10
});
// verifying the token:
let verified = speakeasy.verify({
...
window : 10
});
默认step
值为30秒,这意味着每30秒生成一个新令牌。如果您希望该令牌仍然验证为"有效"在30秒的时间段之外,您可以指定一个窗口。一个窗口" 10"表示5分钟前和未来5分钟之间(10 * 30秒=)之间的所有令牌都有效。
您还可以将步骤设置为5分钟,但如果用户在5分钟有效期结束时收到令牌,则他们可能只剩下10秒钟,直到令牌失效。这就是为什么使用更宽的窗口而不是更大的步骤更好。
确保必须对step
和window
进行speakeasy.totp()
和/或speakeasy.verify()
的任何更改。
答案 1 :(得分:1)
浪费4个小时后,这对我有用,请复制整个代码并尝试一次。整理之后,您可以对其进行修改。
var secret = Speakeasy.generateSecret({length:6}); res.send({“ secret”:secret.base32});
async totpgenerate(request,response) {
response.send({
"token": Speakeasy.time({
secret: request.body.secret,
encoding: "base32",
step:600,//10 mins
window:0
})
})
}
,
async totpvalidate(request,response) {
response.send({
"valid": Speakeasy.time.verify({
secret:request.body.secret,
encoding: 'base32',
token: request.body.token,
step:600,//10 mins
window:0
})
})
}