{"_id":"@bookmie/sjwt","_rev":"7-5058f8ba0b75de99c85c80202c124706","name":"@bookmie/sjwt","dist-tags":{"latest":"1.0.6"},"versions":{"1.0.0":{"name":"@bookmie/sjwt","version":"1.0.0","keywords":["jwt","security","verification","revocation","cuckoo-filter","fingerprint","express"],"author":"","license":"ISC","_id":"@bookmie/sjwt@1.0.0","maintainers":[{"name":"bookmie","email":"bookmie.com@gmail.com"}],"dist":{"shasum":"c7d4ac2a7d71c2cd07cf387484da116e0f44c7ad","tarball":"https://registry.npmjs.org/@bookmie/sjwt/-/sjwt-1.0.0.tgz","fileCount":15,"integrity":"sha512-/KTyfTvcKC9kjhuvdq+VemhgPrEyjpMBU/BJ14FEjY3vfbA2HKQqgyAqaOh//rbu70OCpoB+ABhremD1Blxa+Q==","signatures":[{"sig":"MEUCID+OC1CL7IRN9Hjs+xrbZ1VJuABOK3sEBJ6YyJalBsDhAiEAgR7ymdhTSS+G0zwmMXWzC8xLYoq13rUIOPPSmGLm9nU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":37032},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"18a31761c6d494428ebde3fde057447c40e5d0c1","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"bookmie","email":"bookmie.com@gmail.com"},"_npmVersion":"11.14.1","description":"SDK for SJWT Security Platform, wrapping device fingerprinting and JWT revocation operations.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"axios":"^1.7.2"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.3","@types/node":"^20.11.0","@types/express":"^5.0.0"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sjwt_1.0.0_1782761127684_0.8687497795678611","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@bookmie/sjwt","version":"1.0.1","keywords":["jwt","security","verification","revocation","cuckoo-filter","fingerprint","express"],"author":"","license":"ISC","_id":"@bookmie/sjwt@1.0.1","maintainers":[{"name":"bookmie","email":"bookmie.com@gmail.com"}],"dist":{"shasum":"5101b2d6934bc76bb90020075b281489e81fb939","tarball":"https://registry.npmjs.org/@bookmie/sjwt/-/sjwt-1.0.1.tgz","fileCount":10,"integrity":"sha512-/UtTdCO1lSZPnnXffbzdLJ2fbxV8PtVHoGZRadeFDK7LQzKTj7TGRPDvVyejg2va4dn2jlVCLGfUBfjCTxOGyQ==","signatures":[{"sig":"MEYCIQD5aSEcAO5eYNRyoyeoIO9j2S725OnPCGDJOLfU0aQCngIhAILwGr00WsMnXZrOqmRmxi/GTq8VVnLYe9L1e/tDxGBI","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":22675},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"56523363e3d5d8a24c6f7655a585508db45dc3da","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"bookmie","email":"bookmie.com@gmail.com"},"_npmVersion":"11.14.1","description":"SDK for SJWT Security Platform, wrapping device fingerprinting and JWT revocation operations.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"axios":"^1.7.2"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.3","@types/node":"^20.11.0","@types/express":"^5.0.0"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sjwt_1.0.1_1782761641456_0.2493060646779235","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@bookmie/sjwt","version":"1.0.2","keywords":["jwt","security","verification","revocation","cuckoo-filter","fingerprint","express"],"author":"","license":"ISC","_id":"@bookmie/sjwt@1.0.2","maintainers":[{"name":"bookmie","email":"bookmie.com@gmail.com"}],"dist":{"shasum":"d684bf08203606dc7daf23d35bbd71b609a9cb79","tarball":"https://registry.npmjs.org/@bookmie/sjwt/-/sjwt-1.0.2.tgz","fileCount":10,"integrity":"sha512-5E/zyyHqtsAwe5s/r6yamu/8PaO6h3HIhwguWuk/1N+E0g2BzUzVo73CxAsf2b9m/eM9KSoO6Qmivg9Bopzb6w==","signatures":[{"sig":"MEUCIQDksX6f0M9A3tBjb5Y1NFemy9Xa05g+nG2SyW4gEn+acgIgSrdhtYNH1CKJ0+cxAd/LUE9t8vl0eDsKu+gBg4nGjnw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":25460},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"a3512b24ecba9ca6cc60490785876c8c197017c2","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"bookmie","email":"bookmie.com@gmail.com"},"_npmVersion":"12.0.2","description":"SDK for SJWT Security Platform, wrapping device fingerprinting and JWT revocation operations.","directories":{},"_nodeVersion":"26.7.0","dependencies":{"axios":"^1.7.2"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.3","@types/node":"^20.11.0","@types/express":"^5.0.0"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sjwt_1.0.2_1787281687875_0.9542801479525711","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@bookmie/sjwt","version":"1.0.3","keywords":["jwt","security","verification","revocation","cuckoo-filter","fingerprint","express"],"author":"","license":"ISC","_id":"@bookmie/sjwt@1.0.3","maintainers":[{"name":"bookmie","email":"bookmie.com@gmail.com"}],"dist":{"shasum":"6483dd9e27f86ad5078ba6b5b90de3994153df08","tarball":"https://registry.npmjs.org/@bookmie/sjwt/-/sjwt-1.0.3.tgz","fileCount":10,"integrity":"sha512-qGcbkysfsM32GwHSiKoiYolsXaMlfp9x3i2eIlRiFNZ/crtnTZjRZs0QrDyPHy+9PZFjyQBi4FyFHplCzve75Q==","signatures":[{"sig":"MEUCIQDoGOh8rZi3IqPytGYi2HUkYhQQunzE4PzjFEH7FlwQ5gIgAmkJIPISG06KQ+p4DgN5nxwRPKRSVglyVDeIcrt5B1U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":25450},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"84813d7e3528c1844c01834440d9d01e779d514e","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"bookmie","email":"bookmie.com@gmail.com"},"_npmVersion":"12.0.2","description":"SDK for SJWT Security Platform, wrapping device fingerprinting and JWT revocation operations.","directories":{},"_nodeVersion":"26.7.0","dependencies":{"axios":"^1.7.2"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.3","@types/node":"^20.11.0","@types/express":"^5.0.0"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sjwt_1.0.3_1787288034263_0.0657066760968481","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@bookmie/sjwt","version":"1.0.4","keywords":["jwt","security","verification","revocation","cuckoo-filter","fingerprint","express"],"author":"","license":"ISC","_id":"@bookmie/sjwt@1.0.4","maintainers":[{"name":"bookmie","email":"bookmie.com@gmail.com"}],"dist":{"shasum":"f093e6c71bd8ca68c7013db8401598965c877759","tarball":"https://registry.npmjs.org/@bookmie/sjwt/-/sjwt-1.0.4.tgz","fileCount":10,"integrity":"sha512-952d/ALBqkTv4NK2OljPjOKbrTLlkrqkFa9V1v3/in2efFFjmie0Ls3rEtTRwaIrzM0fLV46xvf1WpKxNJBA6g==","signatures":[{"sig":"MEQCIDx1IhVEO+6psIkNs44rLCWdThboIG3ca8uWA4tEadeKAiBgqcjCSpN5H0N9IMUTo9mZAZchDZ3HDiTM5agCL8pNHg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":25916},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"13ffd0a0e676b23ddf096dc835d4dea2bbae8811","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"bookmie","email":"bookmie.com@gmail.com"},"_npmVersion":"12.0.2","description":"SDK for SJWT Security Platform, wrapping device fingerprinting and JWT revocation operations.","directories":{},"_nodeVersion":"26.7.0","dependencies":{"axios":"^1.7.2"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.3","@types/node":"^20.11.0","@types/express":"^5.0.0"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sjwt_1.0.4_1787598088085_0.8391959500424739","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@bookmie/sjwt","version":"1.0.5","keywords":["jwt","security","verification","revocation","cuckoo-filter","fingerprint","express"],"author":"","license":"ISC","_id":"@bookmie/sjwt@1.0.5","maintainers":[{"name":"bookmie","email":"bookmie.com@gmail.com"}],"dist":{"shasum":"c79814325775a608828267e1c5b8ba4c2cbe99b2","tarball":"https://registry.npmjs.org/@bookmie/sjwt/-/sjwt-1.0.5.tgz","fileCount":10,"integrity":"sha512-CabICbCYSqM0EMnRrJVUT9Eryv2SHQR6k9rx44NxlGj+oQ+nJkb6Pmet3wlzHDmFaIMwq/SHgBf5Kg12G2mxuA==","signatures":[{"sig":"MEUCIQCIy02DJa9z/sk7cUrQsSItRx52587hG6ti79zvylpAbgIgOO7yTAvK4F1f3V35QPS+8rsrUO13Af6yFV+0UsfxC80=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":31932},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"3a4539a5f2009a2e1c4702dbae320c29b4b75f6e","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"bookmie","email":"bookmie.com@gmail.com"},"_npmVersion":"12.0.2","description":"SDK for SJWT Security Platform, wrapping device fingerprinting and JWT revocation operations.","directories":{},"_nodeVersion":"26.7.0","dependencies":{"axios":"^1.7.2"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.3.3","@types/node":"^20.11.0","@types/express":"^5.0.0"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sjwt_1.0.5_1787601355472_0.874060670134464","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"@bookmie/sjwt","version":"1.0.6","description":"SDK for SJWT Security Platform, wrapping device fingerprinting and JWT revocation operations.","main":"dist/index.js","types":"dist/index.d.ts","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"keywords":["jwt","security","verification","revocation","cuckoo-filter","fingerprint","express"],"author":"","license":"ISC","dependencies":{"axios":"^1.7.2"},"devDependencies":{"@types/express":"^5.0.0","@types/node":"^20.11.0","typescript":"^5.3.3"},"peerDependencies":{"express":"^4.18.0 || ^5.0.0"},"gitHead":"176ff707faffeeb7e150497c0d4f6594a38b9243","_id":"@bookmie/sjwt@1.0.6","_nodeVersion":"26.7.0","_npmVersion":"12.0.2","dist":{"integrity":"sha512-Qu+qvLlbHlbQ5Kk9yKKV6kxbkeMqBWWyQqdkbqlMwWYABiJ6GLmzJJnWhlu4j8Wa5wrZ6IpI3l3lhQYVEMPPvQ==","shasum":"ba19555857045fbf94ec8aa36a968c6db42367eb","tarball":"https://registry.npmjs.org/@bookmie/sjwt/-/sjwt-1.0.6.tgz","fileCount":10,"unpackedSize":32458,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDCLDNheBkVLuSEZtPQq0mEXZaMToEniXPFT1JUj9oZRAiEA2flep0xpzIrfKEfTsrItRPlmZxxBORUIFmVy1wtx7u0="}]},"_npmUser":{"name":"bookmie","email":"bookmie.com@gmail.com"},"directories":{},"maintainers":[{"name":"bookmie","email":"bookmie.com@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sjwt_1.0.6_1787704761258_0.2573430712155538"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-29T19:25:27.469Z","modified":"2026-08-26T00:39:21.571Z","1.0.0":"2026-06-29T19:25:27.813Z","1.0.1":"2026-06-29T19:34:01.584Z","1.0.2":"2026-08-21T03:08:08.025Z","1.0.3":"2026-08-21T04:53:54.433Z","1.0.4":"2026-08-24T19:01:28.227Z","1.0.5":"2026-08-24T19:55:55.625Z","1.0.6":"2026-08-26T00:39:21.441Z"},"license":"ISC","keywords":["jwt","security","verification","revocation","cuckoo-filter","fingerprint","express"],"description":"SDK for SJWT Security Platform, wrapping device fingerprinting and JWT revocation operations.","maintainers":[{"name":"bookmie","email":"bookmie.com@gmail.com"}],"readme":"# SJWT SDK (Node.js / TypeScript)\n\nSecure JWT (SJWT) SDK for Node.js and TypeScript applications. This SDK provides a simple, type-safe interface for generating, verifying, and rotating JWT tokens, with built-in protection against common vulnerabilities like replay attacks and token theft.\n\n## Features\n\n- **Token Lifecycle Management**: Generate, verify, and rotate JWT tokens with ease.\n- **Security Features**:\n  - **Fingerprint Protection**: Tokens are tied to a unique fingerprint of the device/browser.\n  - **IP Binding**: Tokens are validated against the IP address from which they were issued.\n  - **User-Agent Binding**: Tokens are validated against the User-Agent string.\n  - **Revocation**: Instant token revocation with real-time statistics.\n- **Express Middleware**: Seamless integration with Express.js applications.\n- **TypeScript Support**: Fully typed with TypeScript interfaces and JSDoc.\n\n## Installation\n\n```bash\nnpm install @bookmie/sjwt\n# or\nyarn add @sbookmie/sjwt\n```\n\n## Configuration\n\nYou must configure the SDK using environment variables from your dashboard before initiating the client.\n\n| Environment Variable | Description | Default |\n|----------------------|-------------|---------|\n| `SJWT_PROJECT_ID`    | Your project ID | (Required) |\n| `SJWT_SIGNATURE_KEY` | Your signature key | (Required) |\n\n## Usage\n\n### 1. Initialization\n\nInitialize the SDK by invoking `new SJWT()`. The constructor automatically triggers an initialization check binding your project context.\n\n```typescript\nimport { SJWT } from \"@bookmie/sjwt\";\n\n// Dependencies loaded from process.env automatically\nconst sjwt = new SJWT();\n\n```\n\n### 2. Generating a Token\n\nGenerate a new token with optional payload and TTL. Pass the raw Node/Express incoming request (`req`), and the SDK will automatically extract network fields and build a secure digital fingerprint.\n\n```typescript\n\napp.post(\"/login\", async (req, res) => {\n  const options: SignOptions = {\n    payload: { userId: \"user-123\", role: \"admin\" },\n    ttlSeconds: 3600, // 1 hour\n    type: \"ACCESS\", // ACCESS, REFRESH\n    req // Pass the Express or Node.js request object directly\n  };\n\n  const tokenResponse = await sjwt.sign(options);\n  res.json({ \n    token: tokenResponse.token,\n    tokenType: tokenResponse.tokenType,\n    expiresIn: tokenResponse.expiresIn\n  });\n});\n```\n\n### 3. Verifying a Token\n\nVerify a token manually by providing the raw request. The SDK extracts IP, User-Agent, and Accept-Language for verification automatically.\n\n```typescript\n\napp.get(\"/verify\", async (req, res) => {\n  const result = await sjwt.verify({\n    token: \"your-token\",\n    req // The incoming Express/Node request\n  });\n\n  if (result.valid) {\n    console.log(\"Token is valid. Claims:\", result.claims);\n  } else {\n    console.log(\"Token is invalid. Error:\", result.errorCode);\n  }\n});\n\nif (!result.valid) {\n  switch (result.errorCode) {\n    case \"DEVICE_MISMATCH\":  // stolen token\n    case \"ANOMALY\":  // anomaly flagged\n    //other anomalies\n    case \"REVOKED\":          // already revoked\n  }\n}\n```\n\n### 4. Rotating a Refresh Token\n\nRotate an existing refresh token to generate a new one, optionally with an updated payload and TTL.\n\n```typescript\n\napp.post(\"/refresh\", async (req, res) => {\n  const rotatedToken = await sjwt.rotate({\n    oldToken: \"your-old-refresh-token\",\n    payload: { userId: \"user-123\", role: \"admin\" },\n    ttlSeconds: 3600,\n    req // Pass the incomng request for verification and re-fingerprinting\n  });\n\n  res.json({\n    token: rotatedToken.token,\n    tokenType: rotatedToken.tokenType,\n    expiresIn: rotatedToken.expiresIn\n  });\n});\n```\n\n### 5. Revoking a Token\n\nRevoke a token immediately.\n\n```typescript\n\nawait sjwt.revoke(\"your-token\", \"ACCESS\");\nconsole.log(\"Token revoked.\");\n```\n\n### 6. Express Middleware\n\nIntegrate the verification layer across routes seamlessly with the SJWT Express middleware.\n\n```typescript\nimport express from \"express\";\nimport { SJWT, sjwtMiddleware } from \"@bookmie/sjwt\";\n\nconst app = express();\nconst sjwt = new SJWT();\n\napp.use(express.json());\n\n// Apply globally or on select routes\napp.use(sjwtMiddleware(sjwt));\n\n// Protected route\napp.get(\"/api/protected\", (req, res) => {\n  // If the request makes it here, verification succeeded.\n  // req.sjwt is populated by the middleware containing extracted claims.\n  res.json({ message: \"Access granted\", claims: req.sjwt?.claims });\n});\n\napp.listen(3000, () => console.log(\"Server running on port 3000\"));\n```\n\n## Error Codes\n\nThe `verify()` method and middleware return structured error codes when a token is invalid.\n\n| Error Code | Description |\n|------------|-------------|\n| `REVOKED` | Token has been revoked by the security engine or an admin. |\n| `DEVICE_MISMATCH` | Device fingerprint does not match the one bound to the token. |\n| `INVALID_TOKEN` | Token is malformed, expired, or otherwise unverifiable. |\n| `REPLAY_ATTACK` | Token reuse detected within the replay detection window. |\n| `ANOMALY` | Generic anomaly flagged by the detection engine. |\n| `ANOMALY_HIGH_REQUEST_FREQUENCY` | Unusually high request frequency detected. |\n| `ANOMALY_IP_HOPPING` | Token used from a different IP address than expected. |\n| `ANOMALY_USER_AGENT_CHANGE` | Token used with a different User-Agent than expected. |\n| `HTTP_<status>` | Backend returned an HTTP error (e.g. `HTTP_401`, `HTTP_500`). |\n| `NETWORK_ERROR` | Network failure or timeout during verification. |\n\n### Handling errors\n\n```typescript\nconst result = await sjwt.verify({ token, req });\n\nif (!result.valid) {\n  switch (result.errorCode) {\n    case \"DEVICE_MISMATCH\":\n      // stolen token or device changed\n      break;\n    case \"ANOMALY\":\n    case \"ANOMALY_HIGH_REQUEST_FREQUENCY\":\n    case \"ANOMALY_IP_HOPPING\":\n    case \"ANOMALY_USER_AGENT_CHANGE\":\n      // anomaly flagged\n      break;\n    case \"REPLAY_ATTACK\":\n      // replay detected\n      break;\n    case \"REVOKED\":\n      // token revoked\n      break;\n    case \"INVALID_TOKEN\":\n      // malformed or expired\n      break;\n  }\n}\n```\n\n## Security Considerations\n\n- **Reverse Proxies:** The SDK extracts the IP using the standard `X-Forwarded-For` HTTP header, then falls back to `req.socket.remoteAddress`. If you are running behind a reverse proxy (Nginx, ALB, Cloudflare, etc.), ensure Express is configured to trust the proxy (e.g. `app.set('trust proxy', true)`). \n- **Fingerprint**: The SDK computes a deterministic fingerprint utilizing browser standards sent in headers (`User-Agent` and `Accept-Language`).\n- **Token Rotation**: Rotate refresh tokens to avoid a potential compromise.\n- **Revocation**: The global SJWT threat detection handles instant revocation and blocks blacklisted tokens via a centralized cuckoo filter implementation. Use the revoke functionality immediately when a token acts suspiciously or logout.\n\n## License\n\nISC\n","readmeFilename":"README.md"}