mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor(core): add time window validation tolerance for otp authenticator (#4684)
This commit is contained in:
parent
248448d13a
commit
8c0b55ab06
2 changed files with 20 additions and 23 deletions
|
@ -1,6 +1,17 @@
|
|||
import { authenticator } from 'otplib';
|
||||
|
||||
/**
|
||||
* Note:
|
||||
* Considering T1 and T2 two consecutive time steps,
|
||||
* any token generated within T1 but checked with T2 could be considered valid according to [RFC 6238 5.2](https://datatracker.ietf.org/doc/html/rfc6238#section-5.2).
|
||||
*
|
||||
* FYI: https://github.com/yeojz/otplib/issues/697#issuecomment-1655749578
|
||||
*/
|
||||
// eslint-disable-next-line @silverhand/fp/no-mutation
|
||||
authenticator.options = { window: 1 };
|
||||
|
||||
export const generateTotpSecret = () => authenticator.generateSecret();
|
||||
|
||||
export const validateTotpToken = (secret: string, token: string) =>
|
||||
authenticator.check(token, secret);
|
||||
export const validateTotpToken = (secret: string, token: string) => {
|
||||
return authenticator.check(token, secret);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { authenticator } from 'otplib';
|
||||
|
||||
import { demoAppUrl } from '#src/constants.js';
|
||||
import { waitFor, dcls } from '#src/utils.js';
|
||||
|
||||
import ExpectExperience from './expect-experience.js';
|
||||
|
@ -35,10 +34,7 @@ export default class ExpectTotpExperience extends ExpectExperience {
|
|||
|
||||
const code = authenticator.generate(secret);
|
||||
|
||||
for (const [index, char] of code.split('').entries()) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await this.toFillInput(`totpCode_${index}`, char);
|
||||
}
|
||||
await this.fillTotpCode(code);
|
||||
|
||||
// Wait for the form to commit automatically
|
||||
await waitFor(500);
|
||||
|
@ -64,10 +60,7 @@ export default class ExpectTotpExperience extends ExpectExperience {
|
|||
|
||||
const code = authenticator.generate(secret);
|
||||
|
||||
for (const [index, char] of code.split('').entries()) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await this.toFillInput(`totpCode_${index}`, char);
|
||||
}
|
||||
await this.fillTotpCode(code);
|
||||
|
||||
// Wait for the form to commit automatically
|
||||
await waitFor(500);
|
||||
|
@ -76,17 +69,10 @@ export default class ExpectTotpExperience extends ExpectExperience {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert the page is at the demo app page and get the user ID from the page.
|
||||
* @returns The user ID.
|
||||
*/
|
||||
async getUserIdFromDemoAppPage() {
|
||||
this.toMatchUrl(demoAppUrl);
|
||||
const userIdDiv = await expect(this.page).toMatchElement([dcls('infoCard'), 'div'].join(' '), {
|
||||
text: 'User ID: ',
|
||||
});
|
||||
const userIdSpan = await expect(userIdDiv).toMatchElement('span');
|
||||
|
||||
return (await userIdSpan.evaluate((element) => element.textContent)) ?? '';
|
||||
private async fillTotpCode(code: string) {
|
||||
for (const [index, char] of code.split('').entries()) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await this.toFillInput(`totpCode_${index}`, char);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue