Skip to content

Commit

Permalink
fix: totp code validation (#1228)
Browse files Browse the repository at this point in the history
  • Loading branch information
pozylon committed Jun 28, 2022
1 parent 60d88ed commit 2afcb84
Show file tree
Hide file tree
Showing 4 changed files with 576 additions and 274 deletions.
6 changes: 6 additions & 0 deletions .changeset/nasty-meals-whisper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@accounts/password': patch
'@accounts/two-factor': patch
---

Fix critical issue with "Two-Factor" not validating TOTP codes correctly due to a flawed version of @levminer/speakeasy
2 changes: 1 addition & 1 deletion packages/two-factor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
},
"dependencies": {
"@accounts/types": "^0.33.2",
"@levminer/speakeasy": "1.3.1",
"@levminer/speakeasy": "1.3.3",
"tslib": "2.3.1"
},
"devDependencies": {
Expand Down
43 changes: 19 additions & 24 deletions packages/two-factor/src/two-factor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ export class TwoFactor {
private db!: DatabaseInterface;
private serviceName = 'two-factor';

private verifyTOTPCode(secret: string, code: string): Boolean {
try {
const verified = totp.verify({
secret,
encoding: 'base32',
token: code,
window: this.options.window,
});
if (verified) return true;
} catch (e) {
//
}
return false;
}

constructor(options: AccountsTwoFactorOptions = {}) {
this.options = { ...defaultOptions, ...options };
}
Expand All @@ -39,14 +54,8 @@ export class TwoFactor {
if (!twoFactorService) {
throw new Error(this.options.errors.userTwoFactorNotSet);
}
if (
!totp.verify({
secret: twoFactorService.secret.base32,
encoding: 'base32',
token: code,
window: this.options.window,
})
) {

if (!this.verifyTOTPCode(twoFactorService.secret.base32, code)) {
throw new Error(this.options.errors.codeDidNotMatch);
}
}
Expand Down Expand Up @@ -81,14 +90,7 @@ export class TwoFactor {
throw new Error(this.options.errors.userTwoFactorAlreadySet);
}

if (
totp.verify({
secret: secret.base32,
encoding: 'base32',
token: code,
window: this.options.window,
})
) {
if (this.verifyTOTPCode(secret.base32, code)) {
twoFactorService = {
secret,
};
Expand All @@ -115,14 +117,7 @@ export class TwoFactor {
if (!twoFactorService) {
throw new Error(this.options.errors.userTwoFactorNotSet);
}
if (
totp.verify({
secret: twoFactorService.secret.base32,
encoding: 'base32',
token: code,
window: this.options.window,
})
) {
if (this.verifyTOTPCode(twoFactorService.secret.base32, code)) {
await this.db.unsetService(userId, this.serviceName);
} else {
throw new Error(this.options.errors.codeDidNotMatch);
Expand Down
Loading

0 comments on commit 2afcb84

Please sign in to comment.