From b214c5444ccd5a257c7aac61cc91e277995e87bd Mon Sep 17 00:00:00 2001 From: Lucas Finoti Date: Tue, 14 Jan 2025 13:11:23 -0300 Subject: [PATCH 1/3] chore: replace node-2fa with 2fa-node, update docs, and refactor generateSecret function - Replaced deprecated node-2fa library with 2fa-node for better support and functionality. - Updated project documentation to reflect the new library and changes. - Updated dependencies to their latest versions. - Refactored generateSecret to be asynchronous to fix QR code generation issues (previously relied on the deprecated chart.googleapis.com). --- .npmrc | 1 + README.md | 2 +- docs/content/docs/introduction.md | 2 +- package.json | 61 ++++++++++++++------------- src/two_factor_auth_manager.ts | 11 +++-- tests/two_factor_auth_manager.spec.ts | 8 ++-- tsconfig.json | 8 ++-- 7 files changed, 49 insertions(+), 44 deletions(-) diff --git a/.npmrc b/.npmrc index 43c97e7..62a81f0 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,2 @@ package-lock=false +auto-install-peers=true diff --git a/README.md b/README.md index 8f91cce..ba6770b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ## Introduction -Two Factor Authentication using `node-2fa` integration for AdonisJS. +Two Factor Authentication using `2fa-node` integration for AdonisJS. ## Documentation diff --git a/docs/content/docs/introduction.md b/docs/content/docs/introduction.md index 42dc2bc..d2e09a7 100644 --- a/docs/content/docs/introduction.md +++ b/docs/content/docs/introduction.md @@ -4,7 +4,7 @@ summary: Adonis-2FA is a library for managing Two Factor Authentication in your # Introduction -Adonis-2FA is a library for managing Two Factor Authentication in your AdonisJS project build on top of [node-2fa](https://github.com/jeremyscalpello/node-2fa). +Adonis-2FA is a library for managing Two Factor Authentication in your AdonisJS project build on top of [2fa-node](https://github.com/FinotiLucas/2fa-node). The package it self does not store any secret or data on your behalf. It only give you access the methods to implement a two factor authentication flow and create recovery codes. You can store that information inside a database and use the [auth](https://docs.adonisjs.com/guides/auth) package to login the user within your application. diff --git a/package.json b/package.json index 77b8aac..aab9c1c 100644 --- a/package.json +++ b/package.json @@ -38,35 +38,46 @@ "version": "npm run build", "prepublishOnly": "npm run build" }, - "keywords": [ - "adonisjs", - "2fa", - "adonis" - ], - "author": "brunolipe-a, nulix", - "license": "MIT", "devDependencies": { - "@adonisjs/assembler": "^7.0.0", - "@adonisjs/core": "^6.2.0", - "@adonisjs/eslint-config": "^1.2.1", - "@adonisjs/prettier-config": "^1.2.1", - "@adonisjs/tsconfig": "^1.2.1", + "@adonisjs/assembler": "^7.8.2", + "@adonisjs/core": "^6.17.1", + "@adonisjs/eslint-config": "^1.3.0", + "@adonisjs/prettier-config": "^1.4.0", + "@adonisjs/tsconfig": "^1.4.0", "@japa/assert": "^2.1.0", - "@japa/runner": "^3.1.1", - "@swc/core": "^1.3.102", - "@types/node": "^20.10.7", - "c8": "^9.0.0", + "@japa/runner": "^3.1.4", + "@swc/core": "^1.10.7", + "@types/node": "^20.17.12", + "c8": "^9.1.0", "copyfiles": "^2.4.1", - "del-cli": "^5.0.0", - "eslint": "^8.38.0", + "del-cli": "^5.1.0", + "eslint": "^8.57.1", "np": "^9.2.0", - "prettier": "^3.1.1", + "prettier": "^3.4.2", "ts-node": "^10.9.2", - "typescript": "^5.3.3" + "typescript": "^5.7.3" + }, + "dependencies": { + "2fa-node": "^0.0.4" }, "peerDependencies": { "@adonisjs/core": "^6.2.0" }, + "author": "brunolipe-a, nulix", + "license": "MIT", + "keywords": [ + "adonisjs", + "2fa", + "adonis" + ], + "types": "module", + "eslintConfig": { + "extends": "@adonisjs/eslint-config/package", + "ignorePatterns": [ + "docs/" + ] + }, + "prettier": "@adonisjs/prettier-config", "publishConfig": { "access": "public", "tag": "latest" @@ -87,15 +98,5 @@ "src/**", "!src/types.ts" ] - }, - "eslintConfig": { - "extends": "@adonisjs/eslint-config/package", - "ignorePatterns": [ - "docs/" - ] - }, - "prettier": "@adonisjs/prettier-config", - "dependencies": { - "node-2fa": "^2.0.3" } } diff --git a/src/two_factor_auth_manager.ts b/src/two_factor_auth_manager.ts index 65791c5..c0116e1 100644 --- a/src/two_factor_auth_manager.ts +++ b/src/two_factor_auth_manager.ts @@ -1,4 +1,4 @@ -import * as twoFactor from 'node-2fa' +import * as twoFactor from '2fa-node' import { ResolvedTwoFactorAuthConfig, TwoFactorSecret } from './types.js' import { randomInt } from 'node:crypto' @@ -9,10 +9,11 @@ export class TwoFactorAuthManager { /** * Generate a `Secret` to the given user information */ - generateSecret(userInfo: string): TwoFactorSecret { - return twoFactor.generateSecret({ + async generateSecret(userInfo: string): Promise { + return await twoFactor.generateSecret({ name: this.config.issuer, account: userInfo, + counter: undefined, }) } @@ -29,13 +30,15 @@ export class TwoFactorAuthManager { */ verifyToken(secret: string = '', token: string, recoveryCodes: string[] = []) { const verifyResult = twoFactor.verifyToken(secret, token) + if (!verifyResult) { const isSecretInRecoveryCodes = recoveryCodes.includes(token) return isSecretInRecoveryCodes } - return verifyResult.delta === 0 // Valida token atual, não permitindo token já expirado ou token futuro + return verifyResult + // Valida token atual, não permitindo token já expirado ou token futuro } /** diff --git a/tests/two_factor_auth_manager.spec.ts b/tests/two_factor_auth_manager.spec.ts index 3e8b0f5..125e4dc 100644 --- a/tests/two_factor_auth_manager.spec.ts +++ b/tests/two_factor_auth_manager.spec.ts @@ -9,7 +9,7 @@ test.group('TwoFactorAuthManager', () => { const email = 'johndoe@test.com' const manager = new TwoFactorAuthManager({ issuer }) - const twoFactorSecret = manager.generateSecret(email) + const twoFactorSecret = await manager.generateSecret(email) assert.properties(twoFactorSecret, ['secret', 'uri', 'qr']) assert.equal(twoFactorSecret.secret.length, 32) @@ -46,7 +46,7 @@ test.group('TwoFactorAuthManager', () => { test('it should be able to verify a valid secret and OTP', async ({ assert }) => { const manager = new TwoFactorAuthManager({ issuer }) - const { secret } = manager.generateSecret('any') + const { secret } = await manager.generateSecret('any') const token = manager.generateToken(secret)! @@ -58,7 +58,7 @@ test.group('TwoFactorAuthManager', () => { test('it not should be able to verify a valid secret and invalid OTP', async ({ assert }) => { const manager = new TwoFactorAuthManager({ issuer }) - const { secret } = manager.generateSecret('any') + const { secret } = await manager.generateSecret('any') const isValid = manager.verifyToken(secret, 'something') @@ -68,7 +68,7 @@ test.group('TwoFactorAuthManager', () => { test('it not should be able to verify a invalid secret and valid OTP', async ({ assert }) => { const manager = new TwoFactorAuthManager({ issuer }) - const { secret } = manager.generateSecret('any') + const { secret } = await manager.generateSecret('any') const token = manager.generateToken(secret)! diff --git a/tsconfig.json b/tsconfig.json index dd0bbdb..a0a38cc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,10 +1,10 @@ { "extends": "@adonisjs/tsconfig/tsconfig.package.json", "compilerOptions": { + "target": "esnext", + "moduleResolution": "nodenext", "rootDir": "./", - "outDir": "./build", + "outDir": "./build" }, - "exclude": [ - "docs" - ] + "exclude": ["docs"] } From 638a8b5489953a230e91ea2bf208bb918d82e8f4 Mon Sep 17 00:00:00 2001 From: Lucas Finoti <42899930+FinotiLucas@users.noreply.github.com> Date: Fri, 17 Jan 2025 13:10:19 -0300 Subject: [PATCH 2/3] update dependencies --- package.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index aab9c1c..b9d8afd 100644 --- a/package.json +++ b/package.json @@ -44,21 +44,21 @@ "@adonisjs/eslint-config": "^1.3.0", "@adonisjs/prettier-config": "^1.4.0", "@adonisjs/tsconfig": "^1.4.0", - "@japa/assert": "^2.1.0", - "@japa/runner": "^3.1.4", + "@japa/assert": "^4.0.1", + "@japa/runner": "^4.1.0", "@swc/core": "^1.10.7", - "@types/node": "^20.17.12", - "c8": "^9.1.0", + "@types/node": "^22.10.7", + "c8": "^10.1.3", "copyfiles": "^2.4.1", - "del-cli": "^5.1.0", - "eslint": "^8.57.1", - "np": "^9.2.0", + "del-cli": "^6.0.0", + "eslint": "^9.18.0", + "np": "^10.1.0", "prettier": "^3.4.2", "ts-node": "^10.9.2", "typescript": "^5.7.3" }, "dependencies": { - "2fa-node": "^0.0.4" + "2fa-node": "^0.0.5" }, "peerDependencies": { "@adonisjs/core": "^6.2.0" From 71ea7656f8a53cbb5081c672a29a7f0fc12fa052 Mon Sep 17 00:00:00 2001 From: Lucas Finoti <42899930+FinotiLucas@users.noreply.github.com> Date: Sat, 18 Jan 2025 15:40:07 -0300 Subject: [PATCH 3/3] fix lint issues --- .github/lock.yml | 2 +- .github/stale.yml | 2 +- README.md | 7 ++----- docs/bin/serve.ts | 2 +- docs/content/.DS_Store | Bin 10244 -> 0 bytes eslint.config.js | 13 +++++++++++++ package.json | 7 +++++-- providers/two_factor_auth_provider.ts | 1 + src/two_factor_auth_manager.ts | 1 - 9 files changed, 24 insertions(+), 11 deletions(-) delete mode 100644 docs/content/.DS_Store create mode 100644 eslint.config.js diff --git a/.github/lock.yml b/.github/lock.yml index ea7cf67..74eee94 100644 --- a/.github/lock.yml +++ b/.github/lock.yml @@ -1,5 +1,5 @@ --- -ignoreUnless: {{ STALE_BOT }} +ignoreUnless: { { STALE_BOT } } --- # Configuration for Lock Threads - https://github.com/dessant/lock-threads-app diff --git a/.github/stale.yml b/.github/stale.yml index d21cf6c..8b47808 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -1,5 +1,5 @@ --- -ignoreUnless: {{ STALE_BOT }} +ignoreUnless: { { STALE_BOT } } --- # Number of days of inactivity before an issue becomes stale daysUntilStale: 60 diff --git a/README.md b/README.md index ba6770b..ec7d410 100644 --- a/README.md +++ b/README.md @@ -17,12 +17,9 @@ See documentation at [adonis-2fa.netlify.app](https://adonis-2fa.netlify.app) AdonisJS 2FA is open-sourced software licensed under the [MIT license](LICENSE.md). [gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/nulix-dev/adonis-2fa/test.yml?style=for-the-badge -[gh-workflow-url]: https://github.com/nulix-dev/adonis-2fa/actions/workflows/test.yml "Github action" - +[gh-workflow-url]: https://github.com/nulix-dev/adonis-2fa/actions/workflows/test.yml 'Github action' [npm-image]: https://img.shields.io/npm/v/@nulix/adonis-2fa/latest.svg?style=for-the-badge&logo=npm -[npm-url]: https://www.npmjs.com/package/@nulix/adonis-2fa/v/latest "npm" - +[npm-url]: https://www.npmjs.com/package/@nulix/adonis-2fa/v/latest 'npm' [typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript - [license-url]: LICENSE.md [license-image]: https://img.shields.io/github/license/nulix-dev/adonis-2fa?style=for-the-badge diff --git a/docs/bin/serve.ts b/docs/bin/serve.ts index a5dd7c6..7c4de1d 100644 --- a/docs/bin/serve.ts +++ b/docs/bin/serve.ts @@ -57,7 +57,7 @@ async function defineRoutes(app: ApplicationService) { return response.redirect(redirectsCollection[request.url()]) } - for (let collection of collections) { + for (const collection of collections) { await collection.refresh() const entry = collection.findByPermalink(request.url()) if (entry) { diff --git a/docs/content/.DS_Store b/docs/content/.DS_Store deleted file mode 100644 index 7ed6d65aafc46632db9217ee4773bbefaeddb8bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10244 zcmeHMJ4_To82fP?;9v~8ui=B_o zh8SaIqlK~5#KMBc!p0a{>@>z`Vqxt!54oAW2Pn}%GIN>vXJ`I@_WQqoW@l%Qh^%-y zJw)UXk&Vn`Zx@O>iS@HwlR~m33TeTfh7xmrF3(%rYP3y*VZbn87%&VN1`GpxfdTB< zEZLnxn$j>}7%&WMF~FV=4lPJcSsJng z>654V)OzR9pV+GYf&0Oy!oMBgTlMvC>@~kzKQh0&;CGpOn}qKf)JojvVrr?Fm-FOR zDxY!tmrxL@|tMQ)oA9d?J^G244&Wo2wEGT=lbqpJhX%20H8c)&R| zI<~snVIMp?IB{Y2MmFd9_m~IRALKql-Qs$yypLK#2em+UpX+O;8wlK_oR|&A4g_jj zeJwEEZ#^TB>KHk;4hJ)il`A86VbYCIb0XfX&y7)Wi50PkU1z)~quURfyn zne#1wG`>SuHo?PIpUO4bAB4Vgu9g1k!?<3*&hba6RL2hR+lnnDiMfqgtsx@oHmsCh z71PGChpGN=9FwL|MO9xz!zJEYZEOS?Y^7yv3NGTjtfQEi28tRT6$|=HlAk(yRYcA7 zbX;ueQ#-JL6O??z)lv1ouGI)&y7^OVI)QQ26@oDuXz6(J437;YWn{K_x@_yv5%nCe zr=wz83lA^HMa*i(Qc*S2({VWrS4Uv;20jg$b!e@=mWmA;eLp_%`BY~-6p4WGs1 z2m_N01BL;^fMLKeuv-RN!~hQa{(q+N|Npzajj=Zj7zXw*16Ft{F%<{E-`_-nSVL%V zkgp=M#PljcauXCxg|+j~@wi~0(this.app, twoFactorConfigProvider) if (!config) { throw new RuntimeException( diff --git a/src/two_factor_auth_manager.ts b/src/two_factor_auth_manager.ts index c0116e1..b46fd27 100644 --- a/src/two_factor_auth_manager.ts +++ b/src/two_factor_auth_manager.ts @@ -38,7 +38,6 @@ export class TwoFactorAuthManager { } return verifyResult - // Valida token atual, não permitindo token já expirado ou token futuro } /**