{"_id":"@atlex/auth","_rev":"16-40801df78b87a576fc016f808f2ae25c","name":"@atlex/auth","dist-tags":{"latest":"0.2.2"},"versions":{"0.1.1":{"name":"@atlex/auth","version":"0.1.1","keywords":["atlex","auth","typescript","jwt","session"],"author":{"url":"https://github.com/khamazaspyan","name":"Karen Hamazaspyan"},"license":"MIT","_id":"@atlex/auth@0.1.1","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/atlex-monorepo/issues"},"dist":{"shasum":"f9e93db30db9dd1e811e853f820b33ed96a61096","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.1.1.tgz","fileCount":327,"integrity":"sha512-NRosFMEdNKzwaRpW9aVkTlRDA2mkVOjd5RbkoSx0a6p+wNH3ZmBtWH3TuIBEqWKGPxedb/wuXgX5G+9Fp8lL5A==","signatures":[{"sig":"MEYCIQCIyGHQjNaumH3C5hESoFFgDX1ZZlouMFaKohgUzXb1MgIhAK37LD9/wXDqnvK5lQaivo9j/XaoLreP00m9Ri6ao46M","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":425707},"main":"./dist/index.js","type":"module","_from":"file:atlex-auth-0.1.1.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run -c vitest.config.ts","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"_resolved":"/tmp/f133cf072ee51f413debc12e5d7f893f/atlex-auth-0.1.1.tgz","_integrity":"sha512-NRosFMEdNKzwaRpW9aVkTlRDA2mkVOjd5RbkoSx0a6p+wNH3ZmBtWH3TuIBEqWKGPxedb/wuXgX5G+9Fp8lL5A==","repository":{"url":"git+https://github.com/atlex-framework/atlex-monorepo.git","type":"git","directory":"packages/auth"},"_npmVersion":"10.9.7","description":"JWT and session authentication, guards, and password hashing for Atlex","directories":{},"_nodeVersion":"22.22.2","dependencies":{"jose":"^5.9.6","uuid":"^11.0.5","argon2":"^0.41.1","ioredis":"^5.4.2","bcryptjs":"^2.4.3","@atlex/orm":"0.1.1","@atlex/core":"0.1.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","@types/bcryptjs":"^2.4.6"},"peerDependencies":{"express":"^5.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.1.1_1776194486996_0.35338788792718434","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@atlex/auth","version":"0.1.2","keywords":["atlex","auth","typescript","jwt","session"],"author":{"url":"https://github.com/khamazaspyan","name":"Karen Hamazaspyan"},"license":"MIT","_id":"@atlex/auth@0.1.2","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"dist":{"shasum":"23ffd34ab368495b3134ca4c3eceb5813a2a04c4","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.1.2.tgz","fileCount":327,"integrity":"sha512-VTjJwut2c18bk6QXOW7c0c+EEM6ysvFyKOGlNRRYwmRY3aGLDmcl5rL0QeDs3jm5PgBLe/hhK7nrxjEy1zX9Bg==","signatures":[{"sig":"MEYCIQD9TAnf7I8JBFfZbk8XOeEyDshrjiqv/EAFG8hoPyW2pwIhAPxZ43cG/V1o1ksLqnVVF4LfNPGeTAkTs+KRSnzwWq7R","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":425687},"main":"./dist/index.js","type":"module","_from":"file:atlex-auth-0.1.2.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run -c vitest.config.ts","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"_resolved":"/tmp/533e907166f03a6b6d49fe184bc00456/atlex-auth-0.1.2.tgz","_integrity":"sha512-VTjJwut2c18bk6QXOW7c0c+EEM6ysvFyKOGlNRRYwmRY3aGLDmcl5rL0QeDs3jm5PgBLe/hhK7nrxjEy1zX9Bg==","repository":{"url":"git+https://github.com/atlex-framework/auth.git","type":"git","directory":"packages/auth"},"_npmVersion":"10.9.7","description":"JWT and session authentication, guards, and password hashing for Atlex","directories":{},"_nodeVersion":"22.22.2","dependencies":{"jose":"^5.9.6","uuid":"^11.0.5","argon2":"^0.41.1","ioredis":"^5.4.2","bcryptjs":"^2.4.3","@atlex/orm":"0.1.2","@atlex/core":"0.1.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","@types/bcryptjs":"^2.4.6"},"peerDependencies":{"express":"^5.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.1.2_1776235399415_0.8056370677344187","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@atlex/auth","version":"0.1.3","keywords":["atlex","auth","typescript","jwt","session"],"author":{"url":"https://github.com/khamazaspyan","name":"Karen Hamazaspyan"},"license":"MIT","_id":"@atlex/auth@0.1.3","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"dist":{"shasum":"5bf09935f16632858adff58a71199d4fdff8e024","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.1.3.tgz","fileCount":327,"integrity":"sha512-rmuwsxfpqOfGCVskkzW80ZZ1BENLN6AAW7kovbBkZfPx2o0OF/Wn3rAumTG66BJF145xowgKgpruPF4bZQ/OlA==","signatures":[{"sig":"MEQCIBtMJx8yOHmaGKGnp4HHHTyCoTqMtQWl13sEqe9m+xLEAiBsQrbO9of3opZ45r+vIstEaA/dQNbqRqxJYKqXDLyr6g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":425687},"main":"./dist/index.js","type":"module","_from":"file:atlex-auth-0.1.3.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run -c vitest.config.ts","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"_resolved":"/tmp/4e0e25e0b396d9e5d3dd4ad3d089440c/atlex-auth-0.1.3.tgz","_integrity":"sha512-rmuwsxfpqOfGCVskkzW80ZZ1BENLN6AAW7kovbBkZfPx2o0OF/Wn3rAumTG66BJF145xowgKgpruPF4bZQ/OlA==","repository":{"url":"git+https://github.com/atlex-framework/auth.git","type":"git","directory":"packages/auth"},"_npmVersion":"10.9.7","description":"JWT and session authentication, guards, and password hashing for Atlex","directories":{},"_nodeVersion":"22.22.2","dependencies":{"jose":"^5.9.6","uuid":"^11.0.5","argon2":"^0.41.1","ioredis":"^5.4.2","bcryptjs":"^2.4.3","@atlex/orm":"0.1.3","@atlex/core":"0.1.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","@types/bcryptjs":"^2.4.6"},"peerDependencies":{"express":"^5.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.1.3_1776256087171_0.013391246109958121","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@atlex/auth","version":"0.1.4","keywords":["atlex","authentication","authorization","auth","jwt","jwt-auth","json-web-token","session","session-auth","cookie-auth","guards","middleware-auth","bcrypt","password-hashing","oauth","passport-alternative","sanctum-alternative","laravel-sanctum","laravel-auth","laravel-alternative","nodejs","javascript","typescript"],"author":{"url":"https://github.com/khamazaspyan","name":"Karen Hamazaspyan"},"license":"MIT","_id":"@atlex/auth@0.1.4","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"dist":{"shasum":"4c20d4f794dbb9d21306405fb5a6cbdbeb913e69","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.1.4.tgz","fileCount":327,"integrity":"sha512-eyHof+pboe9XPp7KsXFKS0tz9nLG8pxlcLA/i2P8dt4cveQIudY5ibPB5YNjUVqQXQC+NdwEh7qmhjLvYHF7oQ==","signatures":[{"sig":"MEUCIBLxpt8hOOJDUA24VeoZvromh137dO3chB5VIB0sv0U6AiEAmR2TFeOvybbRxG3HrmkQzVY3xCyvT6Jmf1Ar9c0GfKg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":426124},"main":"./dist/index.js","type":"module","_from":"file:atlex-auth-0.1.4.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run -c vitest.config.ts","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"_resolved":"/tmp/503a5be94890ce03752b6d34e3232bd9/atlex-auth-0.1.4.tgz","_integrity":"sha512-eyHof+pboe9XPp7KsXFKS0tz9nLG8pxlcLA/i2P8dt4cveQIudY5ibPB5YNjUVqQXQC+NdwEh7qmhjLvYHF7oQ==","repository":{"url":"git+https://github.com/atlex-framework/auth.git","type":"git","directory":"packages/auth"},"_npmVersion":"10.9.7","description":"JWT and session authentication, guards, and password hashing for Atlex","directories":{},"_nodeVersion":"22.22.2","dependencies":{"jose":"^5.9.6","uuid":"^11.0.5","argon2":"^0.41.1","ioredis":"^5.4.2","bcryptjs":"^2.4.3","@atlex/orm":"0.1.4","@atlex/core":"0.1.4"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","@types/bcryptjs":"^2.4.6"},"peerDependencies":{"express":"^5.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.1.4_1776259456525_0.4446043090770224","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@atlex/auth","version":"0.1.5","keywords":["atlex","authentication","authorization","auth","jwt","jwt-auth","json-web-token","session","session-auth","cookie-auth","guards","middleware-auth","bcrypt","password-hashing","oauth","passport-alternative","sanctum-alternative","laravel-sanctum","laravel-auth","laravel-alternative","nodejs","javascript","typescript"],"author":{"url":"https://github.com/khamazaspyan","name":"Karen Hamazaspyan"},"license":"MIT","_id":"@atlex/auth@0.1.5","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"dist":{"shasum":"8ec7c7d5a0ae2e72a723c0b1a012e864fc72e2ff","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.1.5.tgz","fileCount":327,"integrity":"sha512-kjmytWl7ZDr+vQoFuGltnfiinldhtMd486BdCzPqFgWg9yPx9eE73NdivtukyfB2GbqBC7JybVV+OXcnuyMf2Q==","signatures":[{"sig":"MEQCIDVXJ+nUJMk5ShmgpTcE6i65YEkd5eUcLj8RYEoCxjqdAiB+PXygUW7b5uxRFx+IIyt/UGrtMH7OLtsxvnQlOCWCFg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":426124},"main":"./dist/index.js","type":"module","_from":"file:atlex-auth-0.1.5.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run -c vitest.config.ts","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"_resolved":"/tmp/7178e0557df2e72e78a9c901c00b53a8/atlex-auth-0.1.5.tgz","_integrity":"sha512-kjmytWl7ZDr+vQoFuGltnfiinldhtMd486BdCzPqFgWg9yPx9eE73NdivtukyfB2GbqBC7JybVV+OXcnuyMf2Q==","repository":{"url":"git+https://github.com/atlex-framework/auth.git","type":"git","directory":"packages/auth"},"_npmVersion":"10.9.7","description":"JWT and session authentication, guards, and password hashing for Atlex","directories":{},"_nodeVersion":"22.22.2","dependencies":{"jose":"^5.9.6","uuid":"^11.0.5","argon2":"^0.41.1","ioredis":"^5.4.2","bcryptjs":"^2.4.3","@atlex/orm":"0.1.5","@atlex/core":"0.1.5"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","@types/bcryptjs":"^2.4.6"},"peerDependencies":{"express":"^5.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.1.5_1776260732364_0.7189611812402017","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"@atlex/auth","version":"0.1.6","keywords":["atlex","authentication","authorization","auth","jwt","jwt-auth","json-web-token","session","session-auth","cookie-auth","guards","middleware-auth","bcrypt","password-hashing","oauth","passport-alternative","sanctum-alternative","laravel-sanctum","laravel-auth","laravel-alternative","nodejs","javascript","typescript"],"author":{"url":"https://github.com/khamazaspyan","name":"Karen Hamazaspyan"},"license":"MIT","_id":"@atlex/auth@0.1.6","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"dist":{"shasum":"391c524d354e134dc7dd1769ce126629abf18c10","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.1.6.tgz","fileCount":339,"integrity":"sha512-ljSz+DuPL5ZnSAzQsbkY6OsBEyfX22y1FYaiwzEfO+JYE6dwdiIAZSprfuGZMDWL6X6O7LySjh9mjhzmhcZdvw==","signatures":[{"sig":"MEUCIFB6o+StvuFB1/EbXE1T9BX3PbndVgsJ+gjJQd7KfloGAiEA1DujLB3poU4nWqaCDMkzVpbXw5ohrYVA1rTMYn4ldzQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":454601},"main":"./dist/index.js","type":"module","_from":"file:atlex-auth-0.1.6.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run -c vitest.config.ts","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"_resolved":"/tmp/79c03998dbae423c78c6b25506a9e5cb/atlex-auth-0.1.6.tgz","_integrity":"sha512-ljSz+DuPL5ZnSAzQsbkY6OsBEyfX22y1FYaiwzEfO+JYE6dwdiIAZSprfuGZMDWL6X6O7LySjh9mjhzmhcZdvw==","repository":{"url":"git+https://github.com/atlex-framework/auth.git","type":"git","directory":"packages/auth"},"_npmVersion":"10.9.7","description":"JWT and session authentication, guards, and password hashing for Atlex","directories":{},"_nodeVersion":"22.22.2","dependencies":{"jose":"^5.9.6","uuid":"^11.0.5","argon2":"^0.41.1","ioredis":"^5.4.2","bcryptjs":"^2.4.3","@atlex/orm":"0.1.6","@atlex/core":"0.1.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","@types/bcryptjs":"^2.4.6"},"peerDependencies":{"express":"^5.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.1.6_1778694366213_0.829973172755178","host":"s3://npm-registry-packages-npm-production"}},"0.1.7":{"name":"@atlex/auth","version":"0.1.7","keywords":["atlex","authentication","authorization","auth","jwt","jwt-auth","json-web-token","session","session-auth","cookie-auth","guards","middleware-auth","bcrypt","password-hashing","oauth","passport-alternative","sanctum-alternative","laravel-sanctum","laravel-auth","laravel-alternative","nodejs","javascript","typescript"],"author":{"url":"https://github.com/khamazaspyan","name":"Karen Hamazaspyan"},"license":"MIT","_id":"@atlex/auth@0.1.7","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"dist":{"shasum":"71d714b0219a61542b2de95569f3539862b531c4","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.1.7.tgz","fileCount":339,"integrity":"sha512-lUdU29DI1lgtjFs3HC0Wb71Kgau5OLLciF3gXksLNQ+s5Mkl37fa0RiXPIWnrp0pAG8OX0j6L9GXU8NzmKMIfg==","signatures":[{"sig":"MEYCIQCYz5/AJ9UQCsQas4D4MfI6V08xInclUoCiNif9fHx6wgIhAMwr0Ij4FPXfKeMreHQek0iT7WUgr3vNA1Iz9bBvVvgO","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":454601},"main":"./dist/index.js","type":"module","_from":"file:atlex-auth-0.1.7.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run -c vitest.config.ts","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"_resolved":"/tmp/21811f9089a2bb44165327f7fca3671b/atlex-auth-0.1.7.tgz","_integrity":"sha512-lUdU29DI1lgtjFs3HC0Wb71Kgau5OLLciF3gXksLNQ+s5Mkl37fa0RiXPIWnrp0pAG8OX0j6L9GXU8NzmKMIfg==","repository":{"url":"git+https://github.com/atlex-framework/auth.git","type":"git","directory":"packages/auth"},"_npmVersion":"10.9.7","description":"JWT and session authentication, guards, and password hashing for Atlex","directories":{},"_nodeVersion":"22.22.2","dependencies":{"jose":"^5.9.6","uuid":"^11.0.5","argon2":"^0.41.1","ioredis":"^5.4.2","bcryptjs":"^2.4.3","@atlex/orm":"0.1.7","@atlex/core":"0.1.7"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","@types/bcryptjs":"^2.4.6"},"peerDependencies":{"express":"^5.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.1.7_1778755094151_0.8500200555671384","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"@atlex/auth","version":"0.1.8","keywords":["atlex","authentication","authorization","auth","jwt","jwt-auth","json-web-token","session","session-auth","cookie-auth","guards","middleware-auth","bcrypt","password-hashing","oauth","passport-alternative","sanctum-alternative","laravel-sanctum","laravel-auth","laravel-alternative","nodejs","javascript","typescript"],"author":{"url":"https://github.com/khamazaspyan","name":"Karen Hamazaspyan"},"license":"MIT","_id":"@atlex/auth@0.1.8","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"dist":{"shasum":"a378361d33e93f1698d0ae41bd783befa856d199","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.1.8.tgz","fileCount":339,"integrity":"sha512-ox/Ux9MPwRhPeexjl/DYVyqABGsKS23HgSVp8deUPnpAQaylm1F59M+IABas2Jt2YNTgkE33psNvlbKv4UvOfg==","signatures":[{"sig":"MEUCIDIKwv5+f4NZ2lmJtcFfmR3/GFr0rBMt/L2AA3A7HtBRAiEAuOhfWrjbajkkvx4xVoUQ7FYlYngw6bTEd69x+SChS5M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":454601},"main":"./dist/index.js","type":"module","_from":"file:atlex-auth-0.1.8.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run -c vitest.config.ts","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"_resolved":"/tmp/c63270fdb0b244f5bb8a90d25cff9586/atlex-auth-0.1.8.tgz","_integrity":"sha512-ox/Ux9MPwRhPeexjl/DYVyqABGsKS23HgSVp8deUPnpAQaylm1F59M+IABas2Jt2YNTgkE33psNvlbKv4UvOfg==","repository":{"url":"git+https://github.com/atlex-framework/auth.git","type":"git","directory":"packages/auth"},"_npmVersion":"10.9.7","description":"JWT and session authentication, guards, and password hashing for Atlex","directories":{},"_nodeVersion":"22.22.2","dependencies":{"jose":"^5.9.6","uuid":"^11.0.5","argon2":"^0.41.1","ioredis":"^5.4.2","bcryptjs":"^2.4.3","@atlex/orm":"0.1.8","@atlex/core":"0.1.8"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","@types/bcryptjs":"^2.4.6"},"peerDependencies":{"express":"^5.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.1.8_1778775534430_0.9536031815512374","host":"s3://npm-registry-packages-npm-production"}},"0.1.9":{"name":"@atlex/auth","version":"0.1.9","keywords":["atlex","authentication","authorization","auth","jwt","jwt-auth","json-web-token","session","session-auth","cookie-auth","guards","middleware-auth","bcrypt","password-hashing","oauth","passport-alternative","sanctum-alternative","laravel-sanctum","laravel-auth","laravel-alternative","nodejs","javascript","typescript"],"author":{"url":"https://github.com/khamazaspyan","name":"Karen Hamazaspyan"},"license":"MIT","_id":"@atlex/auth@0.1.9","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"dist":{"shasum":"11b5ddb810946ebdbef27fc8b34dc683797e7260","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.1.9.tgz","fileCount":339,"integrity":"sha512-yku+4sVGGYABuq6rSdl0Im9tg2bp9K2PxmsZ7pRLIjkxSQ5gOEFB87+gcVmpPSUbpN20R58qgVNc+mJuyO2rXA==","signatures":[{"sig":"MEUCIQDNDWa2jkltksqoaj53iQZArq93Sg9q5yjpbYQmAR9x+AIgcMMgO0BgyN/3Ry6++86yeIsxKyzE6ZyVcwlY76Y/JMo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":454602},"main":"./dist/index.js","type":"module","_from":"file:atlex-auth-0.1.9.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run -c vitest.config.ts","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"_resolved":"/tmp/f6336b0affdcd55515f4538022c24a7f/atlex-auth-0.1.9.tgz","_integrity":"sha512-yku+4sVGGYABuq6rSdl0Im9tg2bp9K2PxmsZ7pRLIjkxSQ5gOEFB87+gcVmpPSUbpN20R58qgVNc+mJuyO2rXA==","repository":{"url":"git+https://github.com/atlex-framework/auth.git","type":"git","directory":"packages/auth"},"_npmVersion":"10.9.7","description":"JWT and session authentication, guards, and password hashing for Atlex","directories":{},"_nodeVersion":"22.22.2","dependencies":{"jose":"^5.9.6","uuid":"^11.0.5","argon2":"^0.41.1","ioredis":"^5.4.2","bcryptjs":"^2.4.3","@atlex/orm":"0.1.10","@atlex/core":"0.1.9"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","@types/bcryptjs":"^2.4.6"},"peerDependencies":{"express":"^5.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.1.9_1778830258863_0.3660456190776107","host":"s3://npm-registry-packages-npm-production"}},"0.1.10":{"name":"@atlex/auth","version":"0.1.10","keywords":["atlex","authentication","authorization","auth","jwt","jwt-auth","json-web-token","session","session-auth","cookie-auth","guards","middleware-auth","bcrypt","password-hashing","oauth","passport-alternative","sanctum-alternative","laravel-sanctum","laravel-auth","laravel-alternative","nodejs","javascript","typescript"],"author":{"url":"https://github.com/khamazaspyan","name":"Karen Hamazaspyan"},"license":"MIT","_id":"@atlex/auth@0.1.10","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"dist":{"shasum":"4bdbda4323a469121551917ef940cda1780300aa","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.1.10.tgz","fileCount":339,"integrity":"sha512-yYgX6vtc3JIt7DUCl8EjIFtKqOY77rC6VzCJD+zywg8fsNLnZQZLX4H+cj4nohfy7HQTev501Qe7xb9FvUyWcQ==","signatures":[{"sig":"MEQCIH8xVI7TfAu6v5Jd3T6sjxfFPkFBXPx3QGtSvTBdQ/+FAiBnpdA7Ogi1wOO02wFOX6GlGJDqMzgUUobJEiiv6Xzw6w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":454604},"main":"./dist/index.js","type":"module","_from":"file:atlex-auth-0.1.10.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run -c vitest.config.ts","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"_resolved":"/tmp/57b53a90f8fcf5a35f57f577480fd136/atlex-auth-0.1.10.tgz","_integrity":"sha512-yYgX6vtc3JIt7DUCl8EjIFtKqOY77rC6VzCJD+zywg8fsNLnZQZLX4H+cj4nohfy7HQTev501Qe7xb9FvUyWcQ==","repository":{"url":"git+https://github.com/atlex-framework/auth.git","type":"git","directory":"packages/auth"},"_npmVersion":"10.9.7","description":"JWT and session authentication, guards, and password hashing for Atlex","directories":{},"_nodeVersion":"22.22.2","dependencies":{"jose":"^5.9.6","uuid":"^11.0.5","argon2":"^0.41.1","ioredis":"^5.4.2","bcryptjs":"^2.4.3","@atlex/orm":"0.1.10","@atlex/core":"0.1.10"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","@types/bcryptjs":"^2.4.6"},"peerDependencies":{"express":"^5.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.1.10_1778834112899_0.6062510182961476","host":"s3://npm-registry-packages-npm-production"}},"0.1.11":{"name":"@atlex/auth","version":"0.1.11","keywords":["atlex","authentication","authorization","auth","jwt","jwt-auth","json-web-token","session","session-auth","cookie-auth","guards","middleware-auth","bcrypt","password-hashing","oauth","passport-alternative","sanctum-alternative","laravel-sanctum","laravel-auth","laravel-alternative","nodejs","javascript","typescript"],"author":{"url":"https://github.com/khamazaspyan","name":"Karen Hamazaspyan"},"license":"MIT","_id":"@atlex/auth@0.1.11","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"dist":{"shasum":"9fd683b4049852e5d32345b5a168f0418e0ceb33","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.1.11.tgz","fileCount":339,"integrity":"sha512-+7kZQ+PjwtHX40C4EeaUbyD9L1w6fmi64gadx1VFS5xZlzAdLGwRU263OpouAsXMtQ74yTs8DMPB1NLeobfMDg==","signatures":[{"sig":"MEUCIGLVHykyOaX4Vf9mWfuODU3x4Z6ZYsDj2AbX4L92iLg2AiEAgyyjY5EW6q1BGl4Zi1NzL900s11fAsDJTnCRvLzvkxg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":454604},"main":"./dist/index.js","type":"module","_from":"file:atlex-auth-0.1.11.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run -c vitest.config.ts","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"_resolved":"/tmp/b7f32f42fb9b2dca85475bf6d44a98e9/atlex-auth-0.1.11.tgz","_integrity":"sha512-+7kZQ+PjwtHX40C4EeaUbyD9L1w6fmi64gadx1VFS5xZlzAdLGwRU263OpouAsXMtQ74yTs8DMPB1NLeobfMDg==","repository":{"url":"git+https://github.com/atlex-framework/auth.git","type":"git","directory":"packages/auth"},"_npmVersion":"10.9.8","description":"JWT and session authentication, guards, and password hashing for Atlex","directories":{},"_nodeVersion":"22.22.3","dependencies":{"jose":"^5.9.6","uuid":"^11.0.5","argon2":"^0.41.1","ioredis":"^5.4.2","bcryptjs":"^2.4.3","@atlex/orm":"0.1.11","@atlex/core":"0.1.11"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","@types/bcryptjs":"^2.4.6"},"peerDependencies":{"express":"^5.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.1.11_1780144966471_0.31918153070263555","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@atlex/auth","version":"0.2.0","keywords":["atlex","authentication","authorization","auth","jwt","jwt-auth","json-web-token","session","session-auth","cookie-auth","guards","middleware-auth","bcrypt","password-hashing","oauth","passport-alternative","sanctum-alternative","laravel-sanctum","laravel-auth","laravel-alternative","nodejs","javascript","typescript"],"author":{"url":"https://github.com/khamazaspyan","name":"Karen Hamazaspyan"},"license":"MIT","_id":"@atlex/auth@0.2.0","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"dist":{"shasum":"73eff6e84f1613b3d14afaae51cbf067b29aa761","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.2.0.tgz","fileCount":339,"integrity":"sha512-rOo6fSdA/FxhdWYjoeItOAjWSVoh4jaeAiGY9YDNyYrJhBlIYpmWN18Ziu+5ZpmgavxPmuFtkA8WOXRHHh16eA==","signatures":[{"sig":"MEUCIF61Rmrr9BJZHglBz84MZAatkGwQbZdxyxU2E0dTVliqAiEA7f+DWqqTUBwUnUDoeGC7j6ZqfHcxZ53IizaYxJX4bII=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":454601},"main":"./dist/index.js","type":"module","_from":"file:atlex-auth-0.2.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run -c vitest.config.ts","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"_resolved":"/tmp/f162a85dd6f9a233328fe6b1a3334ec1/atlex-auth-0.2.0.tgz","_integrity":"sha512-rOo6fSdA/FxhdWYjoeItOAjWSVoh4jaeAiGY9YDNyYrJhBlIYpmWN18Ziu+5ZpmgavxPmuFtkA8WOXRHHh16eA==","repository":{"url":"git+https://github.com/atlex-framework/auth.git","type":"git","directory":"packages/auth"},"_npmVersion":"10.9.8","description":"JWT and session authentication, guards, and password hashing for Atlex","directories":{},"_nodeVersion":"22.22.3","dependencies":{"jose":"^5.9.6","uuid":"^11.0.5","argon2":"^0.41.1","ioredis":"^5.4.2","bcryptjs":"^2.4.3","@atlex/orm":"0.2.0","@atlex/core":"0.2.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","@types/bcryptjs":"^2.4.6"},"peerDependencies":{"express":"^5.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.2.0_1780306556560_0.8855537212750946","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@atlex/auth","version":"0.2.1","keywords":["atlex","authentication","authorization","auth","jwt","jwt-auth","json-web-token","session","session-auth","cookie-auth","guards","middleware-auth","bcrypt","password-hashing","oauth","passport-alternative","sanctum-alternative","laravel-sanctum","laravel-auth","laravel-alternative","nodejs","javascript","typescript"],"author":{"url":"https://github.com/khamazaspyan","name":"Karen Hamazaspyan"},"license":"MIT","_id":"@atlex/auth@0.2.1","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"dist":{"shasum":"b6bd05a2bef23f78242272d1e2a4804dc47bd9e3","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.2.1.tgz","fileCount":339,"integrity":"sha512-uSaFh7Y8hwWYH20UxwAc/MgsyVczTpu1tdOnIvNaYquA1uyK7BWcu1HtNlOGyHlHPsd+MBCPc2qQesVJdQbZtg==","signatures":[{"sig":"MEQCIE4g/eicKdGdh8GnDlbe/YjVuONJK3Y0M9y248EkbBmgAiA8yM6tvz3iI7QjttaahWUukht+vEnHfNAAlUTVhO6F9Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":454601},"main":"./dist/index.js","type":"module","_from":"file:atlex-auth-0.2.1.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"test":"vitest run -c vitest.config.ts","build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json"},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"_resolved":"/tmp/50819bd3fce3e4777ce5637ad1c85318/atlex-auth-0.2.1.tgz","_integrity":"sha512-uSaFh7Y8hwWYH20UxwAc/MgsyVczTpu1tdOnIvNaYquA1uyK7BWcu1HtNlOGyHlHPsd+MBCPc2qQesVJdQbZtg==","repository":{"url":"git+https://github.com/atlex-framework/auth.git","type":"git","directory":"packages/auth"},"_npmVersion":"10.9.8","description":"JWT and session authentication, guards, and password hashing for Atlex","directories":{},"_nodeVersion":"22.22.3","dependencies":{"jose":"^5.9.6","uuid":"^11.0.5","argon2":"^0.41.1","ioredis":"^5.4.2","bcryptjs":"^2.4.3","@atlex/orm":"0.2.1","@atlex/core":"0.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^3.2.4","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","@types/bcryptjs":"^2.4.6"},"peerDependencies":{"express":"^5.1.0"},"_npmOperationalInternal":{"tmp":"tmp/auth_0.2.1_1780423675548_0.2425375172229265","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@atlex/auth","version":"0.2.2","description":"JWT and session authentication, guards, and password hashing for Atlex","type":"module","license":"MIT","author":{"name":"Karen Hamazaspyan","url":"https://github.com/khamazaspyan"},"keywords":["atlex","authentication","authorization","auth","jwt","jwt-auth","json-web-token","session","session-auth","cookie-auth","guards","middleware-auth","bcrypt","password-hashing","oauth","passport-alternative","sanctum-alternative","laravel-sanctum","laravel-auth","laravel-alternative","nodejs","javascript","typescript"],"engines":{"node":">=20"},"repository":{"type":"git","url":"git+https://github.com/atlex-framework/auth.git","directory":"packages/auth"},"homepage":"https://atlex.dev","bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"publishConfig":{"access":"public"},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"peerDependencies":{"express":"^5.1.0"},"dependencies":{"argon2":"^0.41.1","bcryptjs":"^2.4.3","ioredis":"^5.4.2","jose":"^5.9.6","uuid":"^11.0.5","@atlex/core":"0.2.2","@atlex/orm":"0.2.2"},"devDependencies":{"@types/bcryptjs":"^2.4.6","@types/express":"^5.0.3","better-sqlite3":"^12.8.0","express":"^5.1.0","typescript":"^6.0.0-dev.20260401","vitest":"^3.2.4"},"scripts":{"build":"tsc -p tsconfig.json","typecheck":"tsc --noEmit -p tsconfig.json","test":"vitest run -c vitest.config.ts"},"_id":"@atlex/auth@0.2.2","_integrity":"sha512-ay8swy3cs9/Ym0VdJ17KCPyOEeTQ0k2+MFWZxhBqHKWKbM7KP/hUwHF2fJfhLphkZ3R0NldgJ8ICPkUtkIWbuQ==","_resolved":"/tmp/9f2521d65177ae61d1a478a2f2fb05ce/atlex-auth-0.2.2.tgz","_from":"file:atlex-auth-0.2.2.tgz","_nodeVersion":"22.23.1","_npmVersion":"10.9.8","dist":{"integrity":"sha512-ay8swy3cs9/Ym0VdJ17KCPyOEeTQ0k2+MFWZxhBqHKWKbM7KP/hUwHF2fJfhLphkZ3R0NldgJ8ICPkUtkIWbuQ==","shasum":"cd2565f9a1bc0e99a83a3602b1db4d2cbbe159da","tarball":"https://registry.npmjs.org/@atlex/auth/-/auth-0.2.2.tgz","fileCount":339,"unpackedSize":454601,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD0gS8jsFeULE+YfXjn/WR1yl0JmUvowk05GBkA04Pr/AIgAVLIFM2EtnxVY7G0vw2YJnAcAkD1lQJEsnR5GknC9us="}]},"_npmUser":{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"},"directories":{},"maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/auth_0.2.2_1784391602234_0.7188639028375763"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-14T19:21:26.872Z","modified":"2026-07-18T16:20:02.502Z","0.1.0-beta":"2026-04-11T21:23:24.014Z","0.1.1":"2026-04-14T19:21:27.176Z","0.1.2":"2026-04-15T06:43:19.590Z","0.1.3":"2026-04-15T12:28:07.361Z","0.1.4":"2026-04-15T13:24:16.679Z","0.1.5":"2026-04-15T13:45:32.587Z","0.1.6":"2026-05-13T17:46:06.436Z","0.1.7":"2026-05-14T10:38:14.358Z","0.1.8":"2026-05-14T16:18:54.609Z","0.1.9":"2026-05-15T07:30:59.024Z","0.1.10":"2026-05-15T08:35:13.046Z","0.1.11":"2026-05-30T12:42:46.624Z","0.2.0":"2026-06-01T09:35:56.689Z","0.2.1":"2026-06-02T18:07:55.711Z","0.2.2":"2026-07-18T16:20:02.374Z"},"bugs":{"url":"https://github.com/atlex-framework/auth/issues"},"author":{"name":"Karen Hamazaspyan","url":"https://github.com/khamazaspyan"},"license":"MIT","homepage":"https://atlex.dev","keywords":["atlex","authentication","authorization","auth","jwt","jwt-auth","json-web-token","session","session-auth","cookie-auth","guards","middleware-auth","bcrypt","password-hashing","oauth","passport-alternative","sanctum-alternative","laravel-sanctum","laravel-auth","laravel-alternative","nodejs","javascript","typescript"],"repository":{"type":"git","url":"git+https://github.com/atlex-framework/auth.git","directory":"packages/auth"},"description":"JWT and session authentication, guards, and password hashing for Atlex","maintainers":[{"name":"khamazaspyan","email":"khamazaspyan@gmail.com"}],"readme":"# @atlex/auth\n\n> Complete authentication system with JWT, sessions, guards, authorization, password hashing, and email verification for Express + Node.js applications.\n\n[![npm version](https://img.shields.io/npm/v/@atlex/auth.svg?style=flat-square&color=7c3aed)](https://www.npmjs.com/package/@atlex/auth)\n[![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?style=flat-square)](https://www.typescriptlang.org/)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE)\n\n[![Buy Me A Coffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-Support-yellow?style=flat-square&logo=buy-me-a-coffee)](https://buymeacoffee.com/khamazaspyan)\n\n## Installation\n\n```bash\nnpm install @atlex/auth\n```\n\n## Quick start\n\nCreate an authenticatable user model:\n\n```typescript\nimport { Authenticatable } from '@atlex/auth'\n\nexport interface User extends Authenticatable {\n  id: string\n  email: string\n  password: string\n  emailVerifiedAt: Date | null\n}\n```\n\nSet up authentication in your service provider:\n\n```typescript\nimport { AuthServiceProvider } from '@atlex/auth'\nimport { Application } from '@atlex/core'\n\nconst app = new Application()\n\napp.register(AuthServiceProvider, {\n  guards: {\n    web: {\n      driver: 'session',\n      provider: 'users',\n    },\n    api: {\n      driver: 'token',\n      provider: 'users',\n    },\n  },\n  providers: {\n    users: async (app) => new DatabaseUserProvider(User),\n  },\n  hashing: {\n    driver: 'bcrypt',\n  },\n})\n```\n\nProtect routes and authenticate users:\n\n```typescript\nimport { AuthMiddleware, StartSession } from '@atlex/auth'\n\n// Use middleware\nrouter.use(StartSession)\nrouter.post('/login', AuthMiddleware, async (req, res) => {\n  const { email, password } = req.body\n\n  if (await auth().attempt(email, password)) {\n    const user = auth().user()\n    res.json({ authenticated: true, user })\n  } else {\n    res.status(401).json({ message: 'Invalid credentials' })\n  }\n})\n```\n\n## Features\n\n### Multi-Guard Authentication\n\n- **SessionGuard**: Cookie-based session authentication\n- **TokenGuard**: JWT/API token authentication\n- Guard-aware `auth()` facade with per-request caching\n- Stateless and stateful guard contracts\n\n### Password Hashing\n\n- **Bcrypt**: Industry-standard with adaptive work factors\n- **Argon2**: OWASP-recommended, memory-hard algorithm\n- **Scrypt**: Key derivation with configurable parameters\n- Hash verification with automatic algorithm detection\n\n### JWT & Tokens\n\n- Token pair support (access + refresh tokens)\n- Configurable expiration windows\n- Token blacklisting with multiple store backends\n- Refresh token repository for persistence\n- Secure token parsing and validation\n\n### Session Management\n\n- Multiple session store backends\n- **FileStore**: File-based session persistence\n- **DatabaseStore**: SQL database session storage\n- **RedisStore**: High-performance Redis backend\n- **CookieStore**: Client-side encrypted sessions\n- **NullStore**: In-memory (development/testing)\n- Configurable session lifetime and garbage collection\n\n### Authorization\n\n- **Gate**: Allow/deny rules for any resource or action\n- **Policies**: Class-based authorization logic\n- Ability checks with user context\n- BeforeCallback hooks for early authorization\n- AfterCallback hooks for conditional enforcement\n\n### Password Reset\n\n- **PasswordBroker**: Secure reset token generation\n- **PasswordBrokerManager**: Multi-broker support\n- Configurable token expiration\n- Email integration ready\n- Verification before reset completion\n\n### Email Verification\n\n- **EmailVerifier**: Track and enforce email verification\n- MustVerifyEmail contract for user models\n- Middleware enforcement with redirect handling\n- Signed verification links\n- Resend verification logic\n\n### Middleware\n\n- **StartSession**: Initialize session per request\n- **AuthMiddleware**: Guard-based authentication check\n- **AuthorizeMiddleware**: Gate/policy enforcement\n- **EnsureEmailIsVerified**: Verification gate\n- **ThrottleLogins**: Brute-force protection with configurable lockout\n\n### Events\n\n- **Attempting**: Before credentials checked\n- **Authenticated**: User successfully authenticated\n- **Login**: User logged in (session/token issued)\n- **Failed**: Authentication failed\n- **Logout**: User logged out\n- **Lockout**: Account locked after failed attempts\n- **PasswordReset**: Password reset complete\n- **PasswordResetLinkSent**: Reset email dispatched\n- **Verified**: Email verified\n- **Registered**: New user registered\n- **CurrentDeviceLogout**: Logout from current device\n- **OtherDeviceLogout**: Logout from other devices\n\n## Core APIs\n\n### AuthManager\n\nCentral facade for authentication operations:\n\n```typescript\nimport { auth } from '@atlex/core'\n\n// Get the active guard (from config)\nconst guard = auth().guard()\n\n// Get a specific named guard\nconst webGuard = auth().guard('web')\nconst apiGuard = auth().guard('api')\n\n// Attempt login with credentials\nconst success = await auth().attempt(email, password)\n\n// Issue login (emit events, create session/token)\nawait auth().login(user)\n\n// Get current authenticated user\nconst user = auth().user()\n\n// Check if authenticated\nconst isAuth = auth().check()\n\n// Check if guest (not authenticated)\nconst isGuest = auth().guest()\n\n// Logout current user\nawait auth().logout()\n\n// Validate password against user's hash\nconst valid = await auth().validate(user, plainPassword)\n\n// Access password broker for reset flows\nconst broker = auth().broker('passwords')\n```\n\n#### Google Social Login\n\nApplications can verify a Google ID token with `GoogleProvider`, then decide how that verified\nprofile maps to their own user table:\n\n```typescript\nimport { app } from '@atlex/core'\nimport { AuthManager, GoogleProvider } from '@atlex/auth'\nimport { config } from '@atlex/config'\n\nconst provider = new GoogleProvider({\n  clientId: config('auth.google.clientId'),\n})\n\nconst auth = app.make<AuthManager>('auth')\nconst user = await auth.socialLogin(provider, idToken, async (socialUser) => {\n  return await User.firstOrCreate(\n    { email: socialUser.email },\n    {\n      name: socialUser.name,\n      google_id: socialUser.googleId,\n      email_verified_at: socialUser.emailVerified ? new Date() : null,\n    },\n  )\n})\n```\n\n`@atlex/auth` verifies provider tokens and returns normalized social profile data. Creating,\nlinking, and persisting application users remains owned by the consuming app.\n\n#### Sign in with Apple\n\nApplications can verify an Apple identity token with `AppleProvider`. Use the Apple services\nID or bundle ID as `clientId`:\n\n```typescript\nimport { app } from '@atlex/core'\nimport { AppleProvider, AuthManager } from '@atlex/auth'\nimport { config } from '@atlex/config'\n\nconst provider = new AppleProvider({\n  clientId: config('auth.apple.clientId'),\n})\n\nconst auth = app.make<AuthManager>('auth')\nconst user = await auth.socialLogin(provider, identityToken, async (socialUser) => {\n  return await User.firstOrCreate(\n    { apple_id: socialUser.appleId },\n    {\n      email: socialUser.email,\n      name: socialUser.name ?? 'Apple User',\n      apple_id: socialUser.appleId,\n      email_verified_at: socialUser.emailVerified ? new Date() : null,\n    },\n  )\n})\n```\n\nApple only sends the user's name on the first sign-in. Store it immediately by verifying the\nidentity token with the first-sign-in profile data before resolving or persisting the user:\n\n```typescript\nconst socialUser = await provider.verify(identityToken, {\n  name: { firstName, lastName },\n})\n\nconst user = await User.firstOrCreate(\n  { apple_id: socialUser.appleId },\n  {\n    email: socialUser.email,\n    name: socialUser.name ?? 'Apple User',\n    apple_id: socialUser.appleId,\n    email_verified_at: socialUser.emailVerified ? new Date() : null,\n  },\n)\n```\n\n### Guards\n\n#### SessionGuard\n\nCookie-based session authentication:\n\n```typescript\nconst guard = auth().guard('web')\n\n// Authenticate user and create session\nawait guard.authenticate(user)\n\n// Get current user\nconst user = guard.user()\n\n// Check authentication\nconst authenticated = guard.check()\n\n// Check guest\nconst guest = guard.guest()\n\n// Logout (destroy session)\nawait guard.logout()\n```\n\n#### TokenGuard\n\nJWT/API token authentication:\n\n```typescript\nconst guard = auth().guard('api')\n\n// Issue token pair (access + refresh)\nconst tokens = await guard.authenticate(user)\n// { accessToken: '...', refreshToken: '...' }\n\n// Get current user from token\nconst user = guard.user()\n\n// Check if token is valid\nconst valid = guard.check()\n\n// Logout (blacklist token)\nawait guard.logout()\n```\n\n### Password Hashing\n\n```typescript\nimport { HashManager, BcryptHasher, Argon2Hasher } from '@atlex/auth'\n\nconst hash = new HashManager({\n  driver: 'bcrypt',\n  bcrypt: { rounds: 12 },\n  argon2: { memory: 65536 },\n})\n\n// Hash a password\nconst digest = await hash.hash('plain-password')\n\n// Verify password against hash\nconst valid = await hash.verify('plain-password', digest)\n\n// Check if hash needs rehashing (algorithm update, etc.)\nconst needsRehash = hash.needsRehash(digest)\n```\n\n### JWT Provider\n\n```typescript\nimport { JwtProvider, RefreshTokenRepository } from '@atlex/auth'\n\nconst jwt = new JwtProvider(config, refreshRepo)\n\n// Create JWT token with custom claims\nconst token = jwt.encode({ sub: user.id, email: user.email })\n\n// Parse and verify token\nconst claims = jwt.decode(token)\n\n// Attempt login and get token pair\nconst result = await jwt.attempt(email, password)\nif (result.succeeded) {\n  console.log(result.accessToken, result.refreshToken)\n}\n\n// Refresh access token\nconst newAccessToken = await jwt.refresh(refreshToken)\n\n// Revoke token via blacklist\nawait jwtBlacklist.blacklist(token)\n```\n\n### Authorization\n\n#### Gate\n\n```typescript\nimport { Gate } from '@atlex/auth'\n\nconst gate = new Gate()\n\n// Define ability\ngate.define('edit-post', (user: User, post: Post) => {\n  return user.id === post.authorId\n})\n\n// Check authorization\nif (gate.allows('edit-post', post)) {\n  // Allow edit\n}\n\n// Or use can/cannot on request context\nconst allowed = req.auth.can('edit-post', post)\nconst denied = req.auth.cannot('edit-post', post)\n\n// Use before callback for admin override\ngate.before((user: User, ability: string) => {\n  if (user.isAdmin) return true\n})\n```\n\n#### Policy\n\n```typescript\nimport { Policy } from '@atlex/auth'\n\nclass PostPolicy extends Policy {\n  view(user: User, post: Post) {\n    return !post.isDraft || user.id === post.authorId\n  }\n\n  edit(user: User, post: Post) {\n    return user.id === post.authorId\n  }\n\n  delete(user: User, post: Post) {\n    return user.id === post.authorId || user.isAdmin\n  }\n}\n\n// Register policy\ngate.policy(Post, PostPolicy)\n\n// Check ability via policy\nif (req.auth.can('edit', post)) {\n  // Allow\n}\n```\n\n### Password Reset\n\n```typescript\nimport { PasswordBroker } from '@atlex/auth'\n\nconst broker = auth().broker('passwords')\n\n// Send reset link to user\nconst sent = await broker.sendResetLink(email)\n\n// Reset password with token\nconst status = await broker.reset(email, token, newPassword)\n\n// Check if token exists and hasn't expired\nconst exists = await broker.tokenExists(email, token)\n```\n\n### Session Management\n\n```typescript\nimport { Session, SessionManager } from '@atlex/auth'\n\nconst sessionManager = new SessionManager(config, store)\n\n// Create new session\nconst session = sessionManager.create()\n\n// Store data in session\nsession.put('user_id', user.id)\nsession.put('cart', { items: [...] })\n\n// Retrieve data\nconst userId = session.get('user_id')\nconst all = session.all()\n\n// Remove data\nsession.forget('cart')\nsession.flush()\n\n// Regenerate ID (security)\nawait session.regenerate()\n```\n\n### Email Verification\n\n```typescript\nimport { EmailVerifier } from '@atlex/auth'\n\nconst verifier = new EmailVerifier(config)\n\n// Generate signed verification link\nconst link = verifier.verificationUrl(user)\n\n// Mark user email as verified\nawait verifier.verify(user)\n\n// Check if user has verified email\nconst isVerified = user.hasVerifiedEmail?.()\n```\n\n## Configuration\n\nCreate `config/auth.ts`:\n\n```typescript\nimport type { AuthConfig } from '@atlex/auth'\nimport { DatabaseUserProvider } from '@atlex/auth'\n\nexport default {\n  defaults: {\n    guard: 'web',\n    provider: 'users',\n  },\n\n  guards: {\n    web: {\n      driver: 'session',\n      provider: 'users',\n    },\n    api: {\n      driver: 'token',\n      provider: 'users',\n    },\n  },\n\n  providers: {\n    users: async (app) => new DatabaseUserProvider(User),\n  },\n\n  jwt: {\n    secret: process.env.JWT_SECRET!,\n    algo: 'HS256',\n    accessTokenExpires: '15m',\n    refreshTokenExpires: '7d',\n    issuer: 'atlex-app',\n  },\n\n  session: {\n    driver: 'cookie',\n    lifetime: 120, // minutes\n    cookieName: 'ATLEXSESSID',\n  },\n\n  hashing: {\n    driver: 'bcrypt',\n    bcrypt: {\n      rounds: 12,\n    },\n    argon2: {\n      memory: 65536,\n      time: 4,\n      parallelism: 1,\n    },\n    scrypt: {\n      cost: 16384,\n      blockSize: 8,\n      parallelization: 1,\n      maxMemory: 64 * 1024 * 1024,\n    },\n  },\n\n  passwords: {\n    table: 'password_resets',\n    expires: 3600, // seconds\n  },\n\n  throttle: {\n    maxAttempts: 5,\n    decay: 60, // minutes\n  },\n} as AuthConfig\n```\n\n## Examples\n\n### Complete Login Flow\n\n```typescript\nimport { Router, Request } from 'express'\nimport { auth, StartSession, AuthMiddleware } from '@atlex/auth'\n\nconst router = Router()\n\nrouter.use(StartSession)\n\n// Login page\nrouter.get('/login', (req, res) => {\n  res.render('login')\n})\n\n// Login handler\nrouter.post('/login', AuthMiddleware, ThrottleLogins, async (req, res) => {\n  const { email, password } = req.body\n\n  const dispatcher = req.app.make('event.dispatcher')\n\n  try {\n    dispatcher.dispatch(new Attempting(email))\n\n    const authenticated = await auth().attempt(email, password)\n\n    if (!authenticated) {\n      dispatcher.dispatch(new Failed(email))\n      return res.status(401).json({ message: 'Invalid credentials' })\n    }\n\n    const user = auth().user()\n\n    dispatcher.dispatch(new Authenticated(user))\n    dispatcher.dispatch(new Login(user))\n\n    res.json({ authenticated: true, user })\n  } catch (error) {\n    if (error instanceof LockoutError) {\n      return res.status(429).json({ message: 'Too many attempts' })\n    }\n    throw error\n  }\n})\n\n// Logout handler\nrouter.post('/logout', async (req, res) => {\n  const user = auth().user()\n\n  await auth().logout()\n\n  req.app.make('event.dispatcher').dispatch(new Logout(user))\n\n  res.json({ message: 'Logged out successfully' })\n})\n\nexport default router\n```\n\n### API Token Authentication\n\n```typescript\nimport { TokenGuard } from '@atlex/auth'\n\nrouter.post('/api/login', async (req, res) => {\n  const { email, password } = req.body\n\n  const guard = auth().guard('api') as TokenGuard\n\n  const result = await guard.attempt(email, password)\n\n  if (!result.succeeded) {\n    return res.status(401).json({ message: 'Invalid credentials' })\n  }\n\n  res.json({\n    accessToken: result.accessToken,\n    refreshToken: result.refreshToken,\n    expiresIn: 900, // 15 minutes\n  })\n})\n\n// Refresh token\nrouter.post('/api/refresh', async (req, res) => {\n  const { refreshToken } = req.body\n\n  try {\n    const newToken = await auth().guard('api').refresh(refreshToken)\n    res.json({ accessToken: newToken })\n  } catch (error) {\n    res.status(401).json({ message: 'Token expired' })\n  }\n})\n```\n\n### Protected Routes with Authorization\n\n```typescript\nimport { AuthorizeMiddleware } from '@atlex/auth'\n\n// Require authentication\nrouter.get(\n  '/dashboard',\n  (req, res, next) => {\n    if (!auth().check()) {\n      return res.redirect('/login')\n    }\n    next()\n  },\n  (req, res) => {\n    const user = auth().user()\n    res.render('dashboard', { user })\n  },\n)\n\n// Require specific ability\nrouter.patch('/posts/:id', AuthorizeMiddleware('edit-post'), async (req, res) => {\n  const post = await Post.find(req.params.id)\n\n  if (!req.auth.can('edit-post', post)) {\n    return res.status(403).json({ message: 'Unauthorized' })\n  }\n\n  // Update post...\n  res.json(post)\n})\n\n// Policy-based authorization\nrouter.delete('/posts/:id', async (req, res) => {\n  const post = await Post.find(req.params.id)\n  const policy = gate.policy(Post)\n\n  if (!policy.delete(auth().user(), post)) {\n    return res.status(403).json({ message: 'Forbidden' })\n  }\n\n  await post.delete()\n  res.json({ message: 'Deleted' })\n})\n```\n\n### Password Reset Flow\n\n```typescript\nrouter.post('/forgot-password', async (req, res) => {\n  const { email } = req.body\n\n  const broker = auth().broker('passwords')\n\n  const sent = await broker.sendResetLink(email)\n\n  res.json({\n    message: 'Password reset link sent to email',\n    sent,\n  })\n})\n\nrouter.post('/reset-password', async (req, res) => {\n  const { email, token, password, password_confirmation } = req.body\n\n  if (password !== password_confirmation) {\n    return res.status(422).json({ message: 'Passwords do not match' })\n  }\n\n  const broker = auth().broker('passwords')\n\n  const status = await broker.reset(email, token, password)\n\n  if (status === PasswordResetStatus.TOKEN_INVALID) {\n    return res.status(422).json({ message: 'Invalid reset token' })\n  }\n\n  res.json({ message: 'Password reset successfully' })\n})\n```\n\n### Email Verification\n\n```typescript\nrouter.get('/email/verify/:id/:hash', async (req, res) => {\n  const user = await User.find(req.params.id)\n\n  if (!user || !verifier.verify(user, req.params.hash)) {\n    return res.status(422).json({ message: 'Invalid verification link' })\n  }\n\n  await user.markEmailAsVerified()\n\n  res.json({ message: 'Email verified successfully' })\n})\n\n// Middleware to require verified email\nrouter.post('/sensitive-action', EnsureEmailIsVerified, async (req, res) => {\n  // Only verified users can reach here\n  const user = auth().user()\n  // ...\n})\n```\n\n## API Overview\n\n### Authentication\n\n- `AuthManager.guard(name?)` - Resolve a guard\n- `AuthManager.attempt(email, password)` - Attempt login\n- `AuthManager.login(user)` - Log user in\n- `AuthManager.user()` - Get current user\n- `AuthManager.check()` - Check if authenticated\n- `AuthManager.guest()` - Check if guest\n- `AuthManager.logout()` - Log user out\n- `AuthManager.validate(user, password)` - Verify password\n- `AuthManager.broker(name)` - Get password broker\n\n### Guards\n\n- `SessionGuard.authenticate(user)` - Create session\n- `SessionGuard.user()` - Get user from session\n- `SessionGuard.check()` - Check session validity\n- `SessionGuard.logout()` - Destroy session\n- `TokenGuard.attempt(email, password)` - Login and issue tokens\n- `TokenGuard.refresh(token)` - Refresh access token\n- `TokenGuard.user()` - Get user from token\n- `TokenGuard.logout()` - Blacklist token\n\n### Password Hashing\n\n- `HashManager.hash(password)` - Hash password\n- `HashManager.verify(password, hash)` - Verify password\n- `HashManager.needsRehash(hash)` - Check if rehash needed\n- `BcryptHasher`, `Argon2Hasher`, `ScryptHasher` - Algorithm implementations\n\n### JWT\n\n- `JwtProvider.encode(claims)` - Create JWT\n- `JwtProvider.decode(token)` - Verify and decode\n- `JwtProvider.attempt(email, password)` - Login and get tokens\n- `JwtBlacklist.blacklist(token)` - Revoke token\n- `RefreshTokenRepository.store(token, user, expiry)` - Store refresh token\n\n### Authorization\n\n- `Gate.define(ability, callback)` - Define ability\n- `Gate.policy(model, Policy)` - Register policy\n- `Gate.allows(ability, ...args)` - Check permission\n- `Gate.denies(ability, ...args)` - Check denial\n- `GateForUser.can(ability, ...args)` - Check as user\n- `Policy` - Base class for policy definitions\n\n### Session\n\n- `Session.put(key, value)` - Store value\n- `Session.get(key)` - Retrieve value\n- `Session.all()` - Get all data\n- `Session.forget(key)` - Remove value\n- `Session.flush()` - Clear session\n- `Session.regenerate()` - Generate new ID\n\n### Password Reset\n\n- `PasswordBroker.sendResetLink(email)` - Send reset link\n- `PasswordBroker.reset(email, token, password)` - Reset password\n- `PasswordBroker.tokenExists(email, token)` - Check token\n\n## Events\n\nAll events are dispatched via `EventDispatcher`:\n\n```typescript\nimport { Attempting, Authenticated, Login, Failed, Logout } from '@atlex/auth'\n\ndispatcher.on(Authenticated, (event) => {\n  console.log('User authenticated:', event.user)\n})\n\ndispatcher.on(Login, (event) => {\n  console.log('User logged in:', event.user)\n})\n\ndispatcher.on(Failed, (event) => {\n  console.log('Authentication failed:', event.email)\n})\n```\n\n## Documentation\n\nFor more information, visit [atlex.dev/guide/auth](https://atlex.dev/guide/auth)\n\n## License\n\n## MIT\n\nPart of [Atlex](https://atlex.dev) — A modern framework for Node.js.\n","readmeFilename":"README.md"}