From 7645490b5f6c1197138b0f9e251d941980f9cb0e Mon Sep 17 00:00:00 2001 From: Icy <185012025+ic4l4s9c@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:38:39 +0300 Subject: [PATCH] feat: switch to cryptographic api provided by `@better-auth/utils` --- package-lock.json | 125 +++++++++++++++++++++++++++----------- package.json | 3 + src/index.ts | 8 +-- src/verify.test.ts | 145 ++++++++++++++++++++++++++------------------- src/verify.ts | 35 ++++++----- 5 files changed, 198 insertions(+), 118 deletions(-) diff --git a/package-lock.json b/package-lock.json index ba10e5e..c320a89 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,16 @@ { "name": "better-auth-telegram", - "version": "0.3.1", + "version": "0.3.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "better-auth-telegram", - "version": "0.3.1", + "version": "0.3.2", "license": "MIT", + "dependencies": { + "@better-auth/utils": "^0.3.0" + }, "devDependencies": { "@biomejs/biome": "2.2.4", "@types/node": "^22.0.0", @@ -117,7 +120,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.3.0.tgz", "integrity": "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==", - "dev": true, "license": "MIT" }, "node_modules/@better-fetch/fetch": { @@ -816,6 +818,7 @@ "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -1402,7 +1405,6 @@ "https://trpc.io/sponsor" ], "license": "MIT", - "peer": true, "peerDependencies": { "typescript": ">=5.7.2" } @@ -1430,6 +1432,7 @@ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -1441,6 +1444,7 @@ "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -1458,7 +1462,8 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/node": { "version": "22.18.8", @@ -1617,7 +1622,6 @@ "integrity": "sha512-hGISOaP18plkzbWEcP/QvtRW1xDXF2+96HbEX6byqQhAUbiS5oH6/9JwW+QsQCIYON2bI6QZBF+2PvOmrRZ9wA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/utils": "3.2.4", "fflate": "^0.8.2", @@ -1655,6 +1659,7 @@ "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" @@ -1665,21 +1670,24 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.13.2", @@ -1687,6 +1695,7 @@ "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", @@ -1698,7 +1707,8 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.14.1", @@ -1706,6 +1716,7 @@ "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -1719,6 +1730,7 @@ "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -1729,6 +1741,7 @@ "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -1738,7 +1751,8 @@ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.14.1", @@ -1746,6 +1760,7 @@ "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -1763,6 +1778,7 @@ "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", @@ -1777,6 +1793,7 @@ "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", @@ -1790,6 +1807,7 @@ "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", @@ -1805,6 +1823,7 @@ "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" @@ -1815,14 +1834,16 @@ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", "dev": true, - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true, - "license": "Apache-2.0" + "license": "Apache-2.0", + "peer": true }, "node_modules/acorn": { "version": "8.15.0", @@ -1830,7 +1851,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1844,6 +1864,7 @@ "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10.13.0" }, @@ -1875,6 +1896,7 @@ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "ajv": "^8.0.0" }, @@ -1893,6 +1915,7 @@ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3" }, @@ -1999,6 +2022,7 @@ "integrity": "sha512-hY/u2lxLrbecMEWSB0IpGzGyDyeoMFQhCvZd2jGFSE5I17Fh01sYUBPCJtkWERw7zrac9+cIghxm/ytJa2X8iA==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "baseline-browser-mapping": "dist/cli.js" } @@ -2137,7 +2161,8 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/bundle-require": { "version": "5.1.0", @@ -2184,7 +2209,8 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "CC-BY-4.0" + "license": "CC-BY-4.0", + "peer": true }, "node_modules/chai": { "version": "5.3.3", @@ -2235,6 +2261,7 @@ "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6.0" } @@ -2425,7 +2452,8 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.228.tgz", "integrity": "sha512-nxkiyuqAn4MJ1QbobwqJILiDtu/jk14hEAWaMiJmNPh1Z+jqoFlBFZjdXwLWGeVSeu9hGLg6+2G9yJaW8rBIFA==", "dev": true, - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -2450,6 +2478,7 @@ "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -2485,7 +2514,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -2527,6 +2555,7 @@ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6" } @@ -2537,6 +2566,7 @@ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -2551,6 +2581,7 @@ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -2564,6 +2595,7 @@ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "engines": { "node": ">=4.0" } @@ -2574,6 +2606,7 @@ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "engines": { "node": ">=4.0" } @@ -2601,6 +2634,7 @@ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.8.x" } @@ -2627,7 +2661,8 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/fast-uri": { "version": "3.1.0", @@ -2644,7 +2679,8 @@ "url": "https://opencollective.com/fastify" } ], - "license": "BSD-3-Clause" + "license": "BSD-3-Clause", + "peer": true }, "node_modules/fdir": { "version": "6.5.0", @@ -2774,14 +2810,16 @@ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, - "license": "BSD-2-Clause" + "license": "BSD-2-Clause", + "peer": true }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, - "license": "ISC" + "license": "ISC", + "peer": true }, "node_modules/happy-dom": { "version": "19.0.2", @@ -2928,6 +2966,7 @@ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -2943,6 +2982,7 @@ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -2985,14 +3025,16 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/json5": { "version": "2.2.3", @@ -3156,6 +3198,7 @@ "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6.11.5" } @@ -3302,7 +3345,8 @@ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/micromatch": { "version": "4.0.8", @@ -3337,6 +3381,7 @@ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 0.6" } @@ -3347,6 +3392,7 @@ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -3488,7 +3534,8 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/node-loader": { "version": "2.1.0", @@ -3515,7 +3562,8 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/nypm": { "version": "0.6.2", @@ -3653,7 +3701,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -3716,7 +3763,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -3805,6 +3851,7 @@ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -3836,6 +3883,7 @@ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -3942,7 +3990,8 @@ "url": "https://feross.org/support" } ], - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/schema-utils": { "version": "4.3.2", @@ -3950,6 +3999,7 @@ "integrity": "sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", @@ -3983,6 +4033,7 @@ "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "license": "BSD-3-Clause", + "peer": true, "dependencies": { "randombytes": "^2.1.0" } @@ -4122,6 +4173,7 @@ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -4133,6 +4185,7 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -4320,6 +4373,7 @@ "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=6" }, @@ -4334,6 +4388,7 @@ "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", @@ -4353,6 +4408,7 @@ "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", @@ -4387,7 +4443,8 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/test-exclude": { "version": "7.0.1", @@ -4678,7 +4735,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -4748,6 +4804,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" @@ -4765,7 +4822,6 @@ "integrity": "sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -4864,7 +4920,6 @@ "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", @@ -4938,6 +4993,7 @@ "integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -5009,6 +5065,7 @@ "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=10.13.0" } diff --git a/package.json b/package.json index c86bff9..424f737 100644 --- a/package.json +++ b/package.json @@ -70,5 +70,8 @@ "*.{js,jsx,ts,tsx,json,jsonc,css,scss,md,mdx}": [ "npx ultracite fix" ] + }, + "dependencies": { + "@better-auth/utils": "^0.3.0" } } diff --git a/src/index.ts b/src/index.ts index 099ff6d..de14721 100644 --- a/src/index.ts +++ b/src/index.ts @@ -115,7 +115,7 @@ export const telegram = (options: TelegramPluginOptions) => { const telegramData = body as TelegramAuthData; // Verify authentication - const isValid = verifyTelegramAuth( + const isValid = await verifyTelegramAuth( telegramData, botToken, maxAuthAge @@ -247,7 +247,7 @@ export const telegram = (options: TelegramPluginOptions) => { const telegramData = body as TelegramAuthData; // Verify authentication - const isValid = verifyTelegramAuth( + const isValid = await verifyTelegramAuth( telegramData, botToken, maxAuthAge @@ -418,7 +418,7 @@ export const telegram = (options: TelegramPluginOptions) => { // Verify initData if ( miniAppValidateInitData && - !verifyMiniAppInitData(initData, botToken, maxAuthAge) + !(await verifyMiniAppInitData(initData, botToken, maxAuthAge)) ) { return ctx.json( { error: "Invalid Mini App initData" }, @@ -552,7 +552,7 @@ export const telegram = (options: TelegramPluginOptions) => { ); } - const isValid = verifyMiniAppInitData( + const isValid = await verifyMiniAppInitData( initData, botToken, maxAuthAge diff --git a/src/verify.test.ts b/src/verify.test.ts index afc487e..e7ee65e 100644 --- a/src/verify.test.ts +++ b/src/verify.test.ts @@ -46,12 +46,12 @@ describe("verifyTelegramAuth", () => { }); describe("Valid authentication", () => { - it("should return true for valid auth data", () => { - const result = verifyTelegramAuth(validAuthData, BotToken); + it("should return true for valid auth data", async () => { + const result = await verifyTelegramAuth(validAuthData, BotToken); expect(result).toBe(true); }); - it("should verify data with only required fields", () => { + it("should verify data with only required fields", async () => { const currentTime = Math.floor(Date.now() / 1000); const minimalData = { id: 123456789, @@ -69,22 +69,25 @@ describe("verifyTelegramAuth", () => { .update(dataCheckString) .digest("hex"); - const result = verifyTelegramAuth({ ...minimalData, hash }, BotToken); + const result = await verifyTelegramAuth( + { ...minimalData, hash }, + BotToken + ); expect(result).toBe(true); }); - it("should verify data with all optional fields", () => { + it("should verify data with all optional fields", async () => { // validAuthData already has all fields - const result = verifyTelegramAuth(validAuthData, BotToken); + const result = await verifyTelegramAuth(validAuthData, BotToken); expect(result).toBe(true); }); - it("should accept auth data within maxAge", () => { - const result = verifyTelegramAuth(validAuthData, BotToken, 86400); + it("should accept auth data within maxAge", async () => { + const result = await verifyTelegramAuth(validAuthData, BotToken, 86400); expect(result).toBe(true); }); - it("should accept auth data from 1 second ago", () => { + it("should accept auth data from 1 second ago", async () => { const oneSecondAgo = Math.floor(Date.now() / 1000) - 1; const data = { ...validAuthData, auth_date: oneSecondAgo }; @@ -104,62 +107,66 @@ describe("verifyTelegramAuth", () => { .update(dataCheckString) .digest("hex"); - const result = verifyTelegramAuth({ ...data, hash }, BotToken, 86400); + const result = await verifyTelegramAuth( + { ...data, hash }, + BotToken, + 86400 + ); expect(result).toBe(true); }); }); describe("Invalid HMAC", () => { - it("should return false for tampered id", () => { + it("should return false for tampered id", async () => { const tamperedData = { ...validAuthData, id: 999999999 }; - const result = verifyTelegramAuth(tamperedData, BotToken); + const result = await verifyTelegramAuth(tamperedData, BotToken); expect(result).toBe(false); }); - it("should return false for tampered first_name", () => { + it("should return false for tampered first_name", async () => { const tamperedData = { ...validAuthData, first_name: "Hacker" }; - const result = verifyTelegramAuth(tamperedData, BotToken); + const result = await verifyTelegramAuth(tamperedData, BotToken); expect(result).toBe(false); }); - it("should return false for tampered username", () => { + it("should return false for tampered username", async () => { const tamperedData = { ...validAuthData, username: "hacker" }; - const result = verifyTelegramAuth(tamperedData, BotToken); + const result = await verifyTelegramAuth(tamperedData, BotToken); expect(result).toBe(false); }); - it("should return false for completely wrong hash", () => { + it("should return false for completely wrong hash", async () => { const tamperedData = { ...validAuthData, hash: "0000000000000000000000000000000000000000000000000000000000000000", }; - const result = verifyTelegramAuth(tamperedData, BotToken); + const result = await verifyTelegramAuth(tamperedData, BotToken); expect(result).toBe(false); }); - it("should return false for empty hash", () => { + it("should return false for empty hash", async () => { const tamperedData = { ...validAuthData, hash: "" }; - const result = verifyTelegramAuth(tamperedData, BotToken); + const result = await verifyTelegramAuth(tamperedData, BotToken); expect(result).toBe(false); }); - it("should return false with wrong bot token", () => { - const result = verifyTelegramAuth(validAuthData, "wrong_token"); + it("should return false with wrong bot token", async () => { + const result = await verifyTelegramAuth(validAuthData, "wrong_token"); expect(result).toBe(false); }); - it("should be case-sensitive for hash", () => { + it("should be case-sensitive for hash", async () => { const uppercaseHash = { ...validAuthData, hash: validAuthData.hash.toUpperCase(), }; - const result = verifyTelegramAuth(uppercaseHash, BotToken); + const result = await verifyTelegramAuth(uppercaseHash, BotToken); expect(result).toBe(false); }); }); describe("Expired auth_date", () => { - it("should return false for auth data older than maxAge", () => { + it("should return false for auth data older than maxAge", async () => { const oldTime = Math.floor(Date.now() / 1000) - 86401; // 1 day + 1 second const oldData = { ...validAuthData, auth_date: oldTime }; @@ -179,11 +186,15 @@ describe("verifyTelegramAuth", () => { .update(dataCheckString) .digest("hex"); - const result = verifyTelegramAuth({ ...oldData, hash }, BotToken, 86400); + const result = await verifyTelegramAuth( + { ...oldData, hash }, + BotToken, + 86400 + ); expect(result).toBe(false); }); - it("should respect custom maxAge parameter", () => { + it("should respect custom maxAge parameter", async () => { const sixtySecondsAgo = Math.floor(Date.now() / 1000) - 60; const data = { ...validAuthData, auth_date: sixtySecondsAgo }; @@ -204,11 +215,11 @@ describe("verifyTelegramAuth", () => { .digest("hex"); // Should fail with maxAge of 30 seconds - const result = verifyTelegramAuth({ ...data, hash }, BotToken, 30); + const result = await verifyTelegramAuth({ ...data, hash }, BotToken, 30); expect(result).toBe(false); }); - it("should accept auth data exactly at maxAge boundary", () => { + it("should accept auth data exactly at maxAge boundary", async () => { const exactlyMaxAge = Math.floor(Date.now() / 1000) - 3600; // exactly 1 hour const data = { ...validAuthData, auth_date: exactlyMaxAge }; @@ -228,13 +239,17 @@ describe("verifyTelegramAuth", () => { .update(dataCheckString) .digest("hex"); - const result = verifyTelegramAuth({ ...data, hash }, BotToken, 3600); + const result = await verifyTelegramAuth( + { ...data, hash }, + BotToken, + 3600 + ); expect(result).toBe(true); }); }); describe("Data ordering", () => { - it("should verify regardless of field order in original data", () => { + it("should verify regardless of field order in original data", async () => { // Create data with fields in different order const unorderedData = { hash: validAuthData.hash, @@ -246,13 +261,13 @@ describe("verifyTelegramAuth", () => { last_name: validAuthData.last_name, } as TelegramAuthData; - const result = verifyTelegramAuth(unorderedData, BotToken); + const result = await verifyTelegramAuth(unorderedData, BotToken); expect(result).toBe(true); }); }); describe("Edge cases", () => { - it("should handle auth_date as 0 (Unix epoch)", () => { + it("should handle auth_date as 0 (Unix epoch)", async () => { const epochData = { ...validAuthData, auth_date: 0 }; // Regenerate hash @@ -272,7 +287,7 @@ describe("verifyTelegramAuth", () => { .digest("hex"); // Should fail because it's way too old - const result = verifyTelegramAuth( + const result = await verifyTelegramAuth( { ...epochData, hash }, BotToken, 86400 @@ -280,7 +295,7 @@ describe("verifyTelegramAuth", () => { expect(result).toBe(false); }); - it("should handle special characters in names", () => { + it("should handle special characters in names", async () => { const currentTime = Math.floor(Date.now() / 1000); const specialCharsData = { id: 123456789, @@ -303,14 +318,14 @@ describe("verifyTelegramAuth", () => { .update(dataCheckString) .digest("hex"); - const result = verifyTelegramAuth( + const result = await verifyTelegramAuth( { ...specialCharsData, hash }, BotToken ); expect(result).toBe(true); }); - it("should handle Unicode in usernames", () => { + it("should handle Unicode in usernames", async () => { const currentTime = Math.floor(Date.now() / 1000); const unicodeData = { id: 123456789, @@ -330,11 +345,14 @@ describe("verifyTelegramAuth", () => { .update(dataCheckString) .digest("hex"); - const result = verifyTelegramAuth({ ...unicodeData, hash }, BotToken); + const result = await verifyTelegramAuth( + { ...unicodeData, hash }, + BotToken + ); expect(result).toBe(true); }); - it("should handle very long photo URLs", () => { + it("should handle very long photo URLs", async () => { const currentTime = Math.floor(Date.now() / 1000); const longUrlData = { id: 123456789, @@ -354,7 +372,10 @@ describe("verifyTelegramAuth", () => { .update(dataCheckString) .digest("hex"); - const result = verifyTelegramAuth({ ...longUrlData, hash }, BotToken); + const result = await verifyTelegramAuth( + { ...longUrlData, hash }, + BotToken + ); expect(result).toBe(true); }); }); @@ -633,22 +654,22 @@ describe("verifyMiniAppInitData", () => { } describe("Valid initData", () => { - it("should return true for valid initData", () => { + it("should return true for valid initData", async () => { const initData = createValidInitData(); - const result = verifyMiniAppInitData(initData, BotToken); + const result = await verifyMiniAppInitData(initData, BotToken); expect(result).toBe(true); }); - it("should verify initData within maxAge", () => { + it("should verify initData within maxAge", async () => { const authDate = Math.floor(Date.now() / 1000) - 3600; // 1 hour ago const initData = createValidInitData(authDate); - const result = verifyMiniAppInitData(initData, BotToken, 86400); + const result = await verifyMiniAppInitData(initData, BotToken, 86400); expect(result).toBe(true); }); - it("should verify minimal initData", () => { + it("should verify minimal initData", async () => { const authDate = Math.floor(Date.now() / 1000); const params = new URLSearchParams({ auth_date: authDate.toString(), @@ -664,63 +685,63 @@ describe("verifyMiniAppInitData", () => { .digest("hex"); params.append("hash", hash); - const result = verifyMiniAppInitData(params.toString(), BotToken); + const result = await verifyMiniAppInitData(params.toString(), BotToken); expect(result).toBe(true); }); }); describe("Invalid initData", () => { - it("should return false for missing hash", () => { + it("should return false for missing hash", async () => { const initData = "auth_date=1234567890&user=%7B%22id%22%3A123%7D"; - const result = verifyMiniAppInitData(initData, BotToken); + const result = await verifyMiniAppInitData(initData, BotToken); expect(result).toBe(false); }); - it("should return false for missing auth_date", () => { + it("should return false for missing auth_date", async () => { const initData = "user=%7B%22id%22%3A123%7D&hash=abc123"; - const result = verifyMiniAppInitData(initData, BotToken); + const result = await verifyMiniAppInitData(initData, BotToken); expect(result).toBe(false); }); - it("should return false for invalid hash", () => { + it("should return false for invalid hash", async () => { const authDate = Math.floor(Date.now() / 1000); const initData = `auth_date=${authDate}&hash=invalid_hash`; - const result = verifyMiniAppInitData(initData, BotToken); + const result = await verifyMiniAppInitData(initData, BotToken); expect(result).toBe(false); }); - it("should return false for tampered data", () => { + it("should return false for tampered data", async () => { const validInitData = createValidInitData(); // Tamper with the data const tamperedData = validInitData.replace("johndoe", "hacker"); - const result = verifyMiniAppInitData(tamperedData, BotToken); + const result = await verifyMiniAppInitData(tamperedData, BotToken); expect(result).toBe(false); }); - it("should return false for expired initData", () => { + it("should return false for expired initData", async () => { const authDate = Math.floor(Date.now() / 1000) - 90000; // >24 hours ago const initData = createValidInitData(authDate); - const result = verifyMiniAppInitData(initData, BotToken, 86400); + const result = await verifyMiniAppInitData(initData, BotToken, 86400); expect(result).toBe(false); }); - it("should return false with wrong bot token", () => { + it("should return false with wrong bot token", async () => { const initData = createValidInitData(); const wrongToken = "987654321:WrongTokenHere"; - const result = verifyMiniAppInitData(initData, wrongToken); + const result = await verifyMiniAppInitData(initData, wrongToken); expect(result).toBe(false); }); }); describe("Security", () => { - it("should use WebAppData constant for secret key", () => { + it("should use WebAppData constant for secret key", async () => { // This tests that we use the correct secret key derivation const authDate = Math.floor(Date.now() / 1000); const params = new URLSearchParams({ auth_date: authDate.toString() }); @@ -732,13 +753,13 @@ describe("verifyMiniAppInitData", () => { .digest("hex"); params.append("hash", wrongHash); - const result = verifyMiniAppInitData(params.toString(), BotToken); + const result = await verifyMiniAppInitData(params.toString(), BotToken); // Should fail because wrong secret key derivation expect(result).toBe(false); }); - it("should verify data-check-string alphabetical sorting", () => { + it("should verify data-check-string alphabetical sorting", async () => { // Test that fields are sorted correctly const authDate = Math.floor(Date.now() / 1000); const params = new URLSearchParams(); @@ -762,7 +783,7 @@ describe("verifyMiniAppInitData", () => { .digest("hex"); params.append("hash", hash); - const result = verifyMiniAppInitData(params.toString(), BotToken); + const result = await verifyMiniAppInitData(params.toString(), BotToken); expect(result).toBe(true); }); diff --git a/src/verify.ts b/src/verify.ts index c39aece..26bb98c 100644 --- a/src/verify.ts +++ b/src/verify.ts @@ -1,4 +1,5 @@ -import { createHash, createHmac } from "node:crypto"; +import { createHash } from "@better-auth/utils/hash"; +import { createHMAC } from "@better-auth/utils/hmac"; import type { TelegramAuthData, TelegramMiniAppData } from "./types"; /** @@ -6,13 +7,13 @@ import type { TelegramAuthData, TelegramMiniAppData } from "./types"; * @param data - Authentication data from Telegram Login Widget * @param botToken - Bot token from @BotFather * @param maxAge - Maximum age of auth in seconds (default: 24 hours) - * @returns true if data is valid, false otherwise + * @returns Promise if data is valid, Promise otherwise */ -export function verifyTelegramAuth( +export async function verifyTelegramAuth( data: TelegramAuthData, botToken: string, maxAge = 86400 -): boolean { +): Promise { // Extract hash from data const { hash, ...dataWithoutHash } = data; @@ -34,15 +35,15 @@ export function verifyTelegramAuth( .join("\n"); // Create secret key: SHA256(bot_token) - const secretKey = createHash("sha256").update(botToken).digest(); + const secretKey = await createHash("SHA-256").digest(botToken); // Calculate HMAC-SHA256 - const hmac = createHmac("sha256", secretKey) - .update(dataCheckString) - .digest("hex"); + const hmac = createHMAC("SHA-256", "hex"); + const ck = await hmac.importKey(secretKey, "sign"); + const calculatedHash = await hmac.sign(ck, dataCheckString); // Compare with received hash - return hmac === hash; + return calculatedHash === hash; } /** @@ -91,13 +92,13 @@ export function parseMiniAppInitData(initData: string): TelegramMiniAppData { * @param initData - Raw initData string from Telegram.WebApp.initData * @param botToken - Bot token from @BotFather * @param maxAge - Maximum age of auth in seconds (default: 24 hours) - * @returns true if data is valid, false otherwise + * @returns Promise if data is valid, false otherwise */ -export function verifyMiniAppInitData( +export async function verifyMiniAppInitData( initData: string, botToken: string, maxAge = 86400 -): boolean { +): Promise { const params = new URLSearchParams(initData); const hash = params.get("hash"); @@ -128,14 +129,12 @@ export function verifyMiniAppInitData( .join("\n"); // Create secret key: HMAC-SHA256("WebAppData", bot_token) - const secretKey = createHmac("sha256", "WebAppData") - .update(botToken) - .digest(); + const secretKey = await createHMAC("SHA-256").sign("WebAppData", botToken); // Calculate HMAC-SHA256 - const calculatedHash = createHmac("sha256", secretKey) - .update(dataCheckString) - .digest("hex"); + const hmac = createHMAC("SHA-256", "hex"); + const ck = await hmac.importKey(secretKey, "sign"); + const calculatedHash = await hmac.sign(ck, dataCheckString); // Compare with received hash return calculatedHash === hash;