{"_id":"@blognami/one-time-token","_rev":"3-dfada87f360933198a8f9ffa0dd74586","name":"@blognami/one-time-token","dist-tags":{"latest":"0.49.0"},"versions":{"0.46.0":{"name":"@blognami/one-time-token","version":"0.46.0","license":"MIT","_id":"@blognami/one-time-token@0.46.0","maintainers":[{"name":"jodysalt","email":"jody@jodysalt.com"}],"homepage":"https://github.com/blognami/blognami#readme","bugs":{"url":"https://github.com/blognami/blognami/issues"},"dist":{"shasum":"9efb10e2982ad901eee9dcb0e975411991713849","tarball":"https://registry.npmjs.org/@blognami/one-time-token/-/one-time-token-0.46.0.tgz","fileCount":12,"integrity":"sha512-Zyw0dogUsIalOXGQW/ITZ4iC5QhMA3p5cb9iSRH6AANxztW6373hjgEOwkx7D6d8uUcIyh8pa80u74iCkE7sCg==","signatures":[{"sig":"MEYCIQCEHLpCggFToLaEagUY+LpHHb7dNJs4LtbmJq2RzaklmwIhAKg4C5n+aYnm/aLldXAhQLgOS6+82Hh1Q4PNZlFPHY1L","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":5056},"type":"module","exports":{".":"./lib/index.js"},"gitHead":"f6bb578630cd5d8d79b014dec4a69f45e4030fcb","_npmUser":{"name":"jodysalt","email":"jody@jodysalt.com"},"repository":{"url":"git://github.com/blognami/blognami.git","type":"git","directory":"packages/@blognami/one-time-token"},"_npmVersion":"11.18.0","description":"A Blognami plugin that provides one-time token (OTP) infrastructure for passwordless authentication. It tracks used tokens to prevent replay attacks and automatically purges expired records.","directories":{},"_nodeVersion":"22.12.0","dependencies":{"blognami":"^0.46.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/one-time-token_0.46.0_1786113022414_0.06670916229397594","host":"s3://npm-registry-packages-npm-production"}},"0.47.0":{"name":"@blognami/one-time-token","version":"0.47.0","license":"MIT","_id":"@blognami/one-time-token@0.47.0","maintainers":[{"name":"jodysalt","email":"jody@jodysalt.com"}],"homepage":"https://github.com/blognami/blognami#readme","bugs":{"url":"https://github.com/blognami/blognami/issues"},"dist":{"shasum":"77133574980ea4e81f98187ef915291eef8e9b2b","tarball":"https://registry.npmjs.org/@blognami/one-time-token/-/one-time-token-0.47.0.tgz","fileCount":12,"integrity":"sha512-wgAjBJEhqnEqiwxjEEf7z8kkwSikC3Avl8WE7PktG0Mz85YYQqRTmBzBK60FaHn9fUeryp/fXiHCFOWij6X51Q==","signatures":[{"sig":"MEUCIQD/r+fm7lTwoOGbfbHVepf0RCYh5pDnkhu2ZDvKIfk4lgIgW03uvgbroQQhqCQ1KdMxv88yIoh7kqhT2R+mfhCAMFo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":5056},"type":"module","exports":{".":"./lib/index.js"},"gitHead":"f7094eab3f29b47f6a241591515ab30ba3d23ca2","_npmUser":{"name":"jodysalt","email":"jody@jodysalt.com"},"repository":{"url":"git://github.com/blognami/blognami.git","type":"git","directory":"packages/@blognami/one-time-token"},"_npmVersion":"11.18.0","description":"A Blognami plugin that provides one-time token (OTP) infrastructure for passwordless authentication. It tracks used tokens to prevent replay attacks and automatically purges expired records.","directories":{},"_nodeVersion":"22.12.0","dependencies":{"blognami":"^0.47.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/one-time-token_0.47.0_1786266039790_0.5517209606681437","host":"s3://npm-registry-packages-npm-production"}},"0.49.0":{"_id":"@blognami/one-time-token@0.49.0","bugs":{"url":"https://github.com/blognami/blognami/issues"},"dist":{"shasum":"f43fd08ad3b4f8a0b5d3b9cc2dd6144d0674f1a9","tarball":"https://registry.npmjs.org/@blognami/one-time-token/-/one-time-token-0.49.0.tgz","fileCount":12,"integrity":"sha512-qiUcnPoVt46osrKRpVqxsXtFgaFgMlWJsdwpH6DLkCRVue7bbIGZU3AujKOTRocCeDryb6nIN9vMvL8F8GaA5Q==","signatures":[{"sig":"MEUCIQD03/1oDZxUlMwsLZPI8pEHb1KttREz4OzVSC4pxGDZ5wIgRf2Fqzg1XdK/Wkm4g3giroiuIylC+owcCv38p55jBN0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHIkDI2SN+KY65KVuiedsuJlOWx3iwNJgA4tFjg99fHDAiAwQ1SgbedSSujDhLEQbmvMiyXLzXabDhmWrqc5xpJP1g=="}],"unpackedSize":5056},"name":"@blognami/one-time-token","type":"module","exports":{".":"./lib/index.js"},"gitHead":"7895b909e32b3b6683a4b2f953be49dad7f26927","license":"MIT","version":"0.49.0","_npmUser":{"name":"jodysalt","email":"jody@jodysalt.com"},"homepage":"https://github.com/blognami/blognami#readme","repository":{"url":"git://github.com/blognami/blognami.git","type":"git","directory":"packages/@blognami/one-time-token"},"_npmVersion":"11.18.0","description":"A Blognami plugin that provides one-time token (OTP) infrastructure for passwordless authentication. It tracks used tokens to prevent replay attacks and automatically purges expired records.","directories":{},"maintainers":[{"name":"jodysalt","email":"jody@jodysalt.com"}],"_nodeVersion":"22.12.0","dependencies":{"blognami":"^0.49.0"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/one-time-token_0.49.0_1790024871669_0.6908951556633804"}}},"time":{"created":"2026-08-07T14:30:22.296Z","modified":"2026-09-21T21:07:51.970Z","0.46.0":"2026-08-07T14:30:22.604Z","0.47.0":"2026-08-09T09:00:39.970Z","0.49.0":"2026-09-21T21:07:51.751Z"},"bugs":{"url":"https://github.com/blognami/blognami/issues"},"license":"MIT","homepage":"https://github.com/blognami/blognami#readme","repository":{"url":"git://github.com/blognami/blognami.git","type":"git","directory":"packages/@blognami/one-time-token"},"description":"A Blognami plugin that provides one-time token (OTP) infrastructure for passwordless authentication. It tracks used tokens to prevent replay attacks and automatically purges expired records.","maintainers":[{"name":"jodysalt","email":"jody@jodysalt.com"}],"readme":"\n# @blognami/one-time-token\n\nA Blognami plugin that provides one-time token (OTP) infrastructure for passwordless authentication. It tracks used tokens to prevent replay attacks and automatically purges expired records.\n\n## Features\n\n- **Replay prevention:** Tracks used token hashes in the database so each OTP can only be verified once.\n- **Automatic cleanup:** A scheduled job runs every 5 minutes to purge expired hash records.\n- **Cryptographic hashing:** Stores SHA-1 hashes of tokens rather than raw values.\n\n## Getting started\n\nInstall the package alongside Blognami:\n\n```bash\nnpm install @blognami/one-time-token\n```\n\nImport it in your project's `lib/index.js`:\n\n```javascript\nimport '@blognami/one-time-token';\n```\n\nInitialize the database to create the required `usedHashes` table:\n\n```bash\nnpx blognami initialize-database\nnpx blognami start-server\n```\n\n## Usage\n\nThe package registers a `oneTimeToken` service that can be accessed from any Blognami context (views, services, commands):\n\n```javascript\nconst { oneTimeToken } = this;\n\n// Check if a token has already been used\nconst used = await oneTimeToken.hasBeenUsed('some-token-key');\n\n// Mark a token as used (with optional expiry, defaults to 24 hours)\nawait oneTimeToken.markAsUsed('some-token-key', {\n    expiresAt: new Date(Date.now() + 1000 * 60 * 10) // 10 minutes\n});\n```\n\n## How it works\n\n1. **`hasBeenUsed(key)`** — Hashes the key with SHA-1 and checks the `usedHashes` table for a matching record.\n2. **`markAsUsed(key, options)`** — Hashes the key and inserts a record into `usedHashes` with an expiration timestamp (defaults to 24 hours).\n3. **Purge job** — A background job runs on a `*/5 * * * *` cron schedule to delete records where `expiresAt` is in the past.\n\n## Database\n\nThis package creates a `usedHashes` table via migration with the following columns:\n\n| Column      | Type     | Description                        |\n|-------------|----------|------------------------------------|\n| `value`     | string   | SHA-1 hash of the token (indexed)  |\n| `expiresAt` | datetime | When the record can be purged (indexed) |\n","readmeFilename":"README.md"}