Created
May 29, 2025 08:23
-
-
Save thuykaka/2b67a58a73375a8df0a3cc9cbbb45f61 to your computer and use it in GitHub Desktop.
2FA Generate & Verify
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import speakeasy from 'speakeasy'; | |
| import qrcode from 'qrcode'; | |
| /* | |
| Steps: | |
| 1. Generate a secret | |
| 2. Show a QR code for the user to scan in | |
| 3. Authenticate the token for the first time | |
| */ | |
| const generateSecret = (name?: string, issuer?: string) => { | |
| return speakeasy.generateSecret({ length: 20, name, issuer }); | |
| }; | |
| const genQrCode = async (otpAuthUrl = '') => { | |
| return qrcode.toDataURL(otpAuthUrl); | |
| }; | |
| const verifyOtp = (otp: string, userSecret: string) => { | |
| return speakeasy.totp.verify({ | |
| secret: userSecret, | |
| encoding: 'base32', | |
| token: otp, | |
| }); | |
| }; | |
| const getRemainingTOTPTime = (step: number) => { | |
| const currentUnixTime = Math.floor(Date.now() / 1000); | |
| return step - (currentUnixTime % step); | |
| }; | |
| const genOtp = (userSecret: string, step = 30): { otp: string; remaining: number } => { | |
| const otp = speakeasy.totp({ secret: userSecret, encoding: 'base32', step }); | |
| const remaining = getRemainingTOTPTime(step); | |
| return { | |
| otp, | |
| remaining, | |
| }; | |
| }; | |
| const setupQrCode = async () => { | |
| // Đầu tiên phải gen 1 secret và gắn cho user | |
| const secret = generateSecret('Thuykaka: thuykaka.app'); | |
| console.log(`secret: ${JSON.stringify(secret)}`); | |
| // Cần lưu lại secret này ở đâu đó cho user, ví dụ | |
| // user.two_factor_temp_secret = secret.base32; | |
| // Hiển thị QR code để người dùng quét | |
| const qrCodeUrl = await genQrCode(secret.otpauth_url); | |
| console.log(`qrCodeUrl: ${qrCodeUrl}`); | |
| }; | |
| const checkGenOtp = () => { | |
| const userSecret = 'EMG4WGZIYMMVP75AJ3YUFWDVYGOWKRVC'; | |
| const otp = genOtp(userSecret); | |
| console.log(`otp: ${JSON.stringify(otp)}`); | |
| }; | |
| const checkVerifyOtp = () => { | |
| const userSecret = 'KRJUQ2DNMMSSSKBUFJXVQNKQLBFDK3ZD'; | |
| const otp = genOtp(userSecret); | |
| console.log(`otp: ${JSON.stringify(otp)}`); | |
| console.log('verifyOtp:', verifyOtp(otp.otp, userSecret)); | |
| }; | |
| // setupQrCode(); | |
| // checkGenOtp(); | |
| // checkVerifyOtp(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment