Skip to content

Replace JWT dependency and remove vulnerable crypto chain#992

Open
PeterDaveHello wants to merge 1 commit into
ChatGPTBox-dev:masterfrom
PeterDaveHello:secure-jwt-dependency-cleanup
Open

Replace JWT dependency and remove vulnerable crypto chain#992
PeterDaveHello wants to merge 1 commit into
ChatGPTBox-dev:masterfrom
PeterDaveHello:secure-jwt-dependency-cleanup

Conversation

@PeterDaveHello

@PeterDaveHello PeterDaveHello commented Jul 1, 2026

Copy link
Copy Markdown
Member

Use a focused HS256 signer backed by @noble/hashes for runtime tokens and Firefox AMO metadata signing. This keeps signing limited to the algorithm this project uses instead of carrying a Node crypto polyfill tree into browser builds.

Keep the existing JWT claims, custom runtime header, token cache behavior, and AMO authorization format intact. Cache entries now track the API key so key changes regenerate tokens instead of reusing a still-valid token signed for another key.

Update uuid and pre-commit to fixed versions without broad force upgrades. Add tests that verify HS256 signatures with node:crypto and cover runtime cache reuse, key changes, expiration, invalid keys, and AMO signing.

Summary by CodeRabbit

  • New Features

    • Improved JWT handling across token generation and release submission flows.
    • Added support for regenerating cached tokens when the API key changes.
  • Bug Fixes

    • Updated build aliases and dependencies to use lighter browser-compatible alternatives.
    • Improved token validation and signing consistency, including standard JWT fields and encoding support.
  • Tests

    • Expanded coverage for JWT signing, verification, and token refresh behavior.

Use a focused HS256 signer backed by @noble/hashes for runtime tokens
and Firefox AMO metadata signing. This keeps signing limited to the
algorithm this project uses instead of carrying a Node crypto polyfill
tree into browser builds.

Keep the existing JWT claims, custom runtime header, token cache
behavior, and AMO authorization format intact. Cache entries now track
the API key so key changes regenerate tokens instead of reusing a
still-valid token signed for another key.

Update uuid and pre-commit to fixed versions without broad force
upgrades. Add tests that verify HS256 signatures with node:crypto and
cover runtime cache reuse, key changes, expiration, invalid keys, and
AMO signing.
@PeterDaveHello PeterDaveHello requested a review from Copilot July 1, 2026 18:30
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Replaces the jsonwebtoken library with a custom HS256 JWT signing utility built on @noble/hashes across token generation and store-submission scripts, removes crypto-browserify, adjusts webpack polyfill aliases, bumps uuid and pre-commit versions, and updates tests to verify tokens via local HMAC helpers.

Changes

JWT signing migration

Layer / File(s) Summary
HS256 JWT signer utility
src/utils/hs256-jwt.mjs, tests/unit/utils/hs256-jwt.test.mjs
New module exports signHs256Jwt, Base64URL-encoding a header/payload and signing with HMAC-SHA256 via @noble/hashes; unit tests cover default/custom headers and UTF-8 payload/secret handling.
Token generator with API-key-aware caching
src/utils/jwt-token-generator.mjs, tests/unit/utils/jwt-token-generator.test.mjs
getToken now signs via signHs256Jwt, caches tokenApiKey, and regenerates tokens when the API key or expiration changes; tests replaced jsonwebtoken decoding/verifying with local HMAC helpers and added an API-key-change regeneration test.
Firefox JWT creation in submit-stores
scripts/submit-stores.mjs, tests/unit/release/submit-stores.test.mjs
createFirefoxJwt now signs via signHs256Jwt instead of jwt.sign; tests add local base64url decode/HMAC verification helpers and assert JWT header/payload fields.
Dependency and build config updates
package.json, build.mjs
Adds @noble/hashes, removes crypto-browserify and jsonwebtoken, bumps uuid and pre-commit; webpack resolve.alias for non-minimal builds replaces the crypto alias with util and stream-browserify aliases.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Script as submit-stores/jwt-token-generator
  participant Signer as signHs256Jwt
  participant Hashes as "`@noble/hashes`"
  Script->>Signer: signHs256Jwt(payload, secret, header)
  Signer->>Signer: base64url encode header and payload
  Signer->>Hashes: hmac(sha256, secret, signingInput)
  Hashes-->>Signer: signature bytes
  Signer-->>Script: header.payload.signature
Loading

Suggested labels: Review effort 4/5

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: replacing the JWT dependency and removing the crypto-related dependency chain.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request replaces the heavy jsonwebtoken and crypto-browserify dependencies with a lightweight, custom HS256 JWT signing utility (hs256-jwt.mjs) powered by @noble/hashes. It also updates the token generator to regenerate tokens when the API key changes, upgrades several dependencies (such as uuid and pre-commit), and adapts the unit tests to verify tokens without relying on jsonwebtoken. Feedback is provided regarding a security vulnerability in the custom signing utility where an undefined secret would be encoded as the literal string "undefined", resulting in a weak signature; adding a validation check to ensure secret is a non-empty string is recommended.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/utils/hs256-jwt.mjs
Comment on lines +19 to +20
function signHs256Jwt(payload, secret, header = { alg: 'HS256', typ: 'JWT' }) {
const encodedHeader = encodeJson(header)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The secret parameter is passed directly to textEncoder.encode(secret). If secret is undefined (for example, due to a missing or malformed API key), TextEncoder will encode the string "undefined" as the secret. This leads to a severe security vulnerability where tokens are signed with a weak, publicly known static string. We should explicitly validate that secret is a non-empty string before encoding it.

Suggested change
function signHs256Jwt(payload, secret, header = { alg: 'HS256', typ: 'JWT' }) {
const encodedHeader = encodeJson(header)
function signHs256Jwt(payload, secret, header = { alg: 'HS256', typ: 'JWT' }) {
if (typeof secret !== 'string' || !secret) {
throw new TypeError('Secret must be a non-empty string')
}
const encodedHeader = encodeJson(header)

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Replace jsonwebtoken with minimal HS256 signer and drop crypto-browserify

🐞 Bug fix ✨ Enhancement 🧪 Tests ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Replace jsonwebtoken with a minimal HS256 JWT signer using @noble/hashes.
• Remove crypto-browserify polyfill wiring to shrink browser bundles and reduce supply-chain risk.
• Strengthen token caching to regenerate on API key changes, and add signature-focused tests.
Diagram

graph TD
  A["scripts/submit-stores.mjs"] --> B["src/utils/hs256-jwt.mjs"] --> C{{"@noble/hashes"}}
  D["src/utils/jwt-token-generator.mjs"] --> B
  E["unit tests"] --> A & D & B
  F(["build.mjs + package.json"]) -. "deps / polyfills" .-> B

  subgraph Legend
    direction LR
    _mod["Module"] ~~~ _cfg(["Config"]) ~~~ _ext{{"External dep"}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Use a general-purpose JWT library (e.g., jose) with tree-shaking
  • ➕ Mature JWT implementation with broader algorithm and validation support
  • ➕ Often provides robust base64url handling and environment abstractions
  • ➖ Heavier dependency footprint than HS256-only needs
  • ➖ May still pull in crypto/polyfill complexity depending on build targets
2. Use WebCrypto/SubtleCrypto for HMAC in browser and node:crypto in Node
  • ➕ Avoids crypto dependencies entirely when WebCrypto is available
  • ➕ Leverages platform primitives directly
  • ➖ Async APIs complicate call sites that currently expect sync signing
  • ➖ Requires conditional implementations and more environment-specific logic
3. Keep jsonwebtoken but hard-externalize crypto polyfills from browser bundles
  • ➕ Minimal code change to signing logic
  • ➕ Avoids maintaining custom JWT assembly code
  • ➖ Retains the broader dependency/supply-chain surface of jsonwebtoken
  • ➖ Bundler config can become fragile across environments and updates

Recommendation: The PR’s approach (a small HS256-only signer backed by @noble/hashes) is a good fit given the project’s fixed algorithm requirements and the goal of removing the crypto-browserify chain from browser builds. One follow-up worth considering is hardening the base64url encoding for Node execution contexts (the release script runs under Node): if Node versions without global btoa/TextEncoder are supported, add a Buffer-based fallback to avoid runtime surprises while keeping the browser-friendly path.

Files changed (8) +169 / -22

Enhancement (2) +30 / -3
submit-stores.mjsSwitch AMO JWT signing to HS256 utility +2/-3

Switch AMO JWT signing to HS256 utility

• Replaces jsonwebtoken-based signing with the new HS256 signer while preserving the AMO JWT claims (iss/jti/iat/exp) and the existing Authorization format expected by Firefox AMO APIs.

scripts/submit-stores.mjs

hs256-jwt.mjsIntroduce minimal HS256 JWT signer +28/-0

Introduce minimal HS256 JWT signer

• Adds a small utility that base64url-encodes header/payload and signs the resulting input using HMAC-SHA256 from @noble/hashes. Supports a default JWT header as well as caller-provided custom headers.

src/utils/hs256-jwt.mjs

Bug fix (1) +11 / -10
jwt-token-generator.mjsUse HS256 signer and regenerate cache on API key changes +11/-10

Use HS256 signer and regenerate cache on API key changes

• Migrates runtime token generation from jsonwebtoken to the HS256 utility and adds iat to the payload. Strengthens cache invalidation by tracking the API key so tokens are regenerated when the signing key changes, even within the expiration window.

src/utils/jwt-token-generator.mjs

Tests (3) +125 / -4
submit-stores.test.mjsVerify AMO JWT signatures using node:crypto +27/-0

Verify AMO JWT signatures using node:crypto

• Adds helpers to decode JWT parts and verify HS256 signatures via node:crypto HMAC. Extends the AMO submission tests to assert the token header fields and time window semantics (exp-iat == 300) plus UUID formatting for jti.

tests/unit/release/submit-stores.test.mjs

hs256-jwt.test.mjsAdd unit tests for HS256 signer utility +57/-0

Add unit tests for HS256 signer utility

• Introduces test coverage validating default headers, custom header preservation, and correct handling of UTF-8 payload/secret values. Verification is performed using node:crypto to ensure interoperability.

tests/unit/utils/hs256-jwt.test.mjs

jwt-token-generator.test.mjsUpdate token generator tests for signature and cache semantics +41/-4

Update token generator tests for signature and cache semantics

• Replaces jsonwebtoken decode/verify usage with local decoding and node:crypto-based HS256 verification. Adds assertions for iat, and adds a new test ensuring cached tokens are regenerated when the API key changes.

tests/unit/utils/jwt-token-generator.test.mjs

Other (2) +3 / -5
build.mjsDrop webpack crypto-browserify polyfill +0/-1

Drop webpack crypto-browserify polyfill

• Removes the explicit crypto polyfill mapping from the webpack fallback configuration, preventing crypto-browserify and its dependency chain from being bundled into browser builds.

build.mjs

package.jsonReplace JWT/crypto deps; bump uuid and pre-commit +3/-4

Replace JWT/crypto deps; bump uuid and pre-commit

• Adds @noble/hashes and removes jsonwebtoken and crypto-browserify from runtime dependencies. Updates uuid and pre-commit to newer pinned ranges to address known issues without broad upgrade churn.

package.json

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR replaces the jsonwebtoken + browser crypto polyfill dependency chain with a small, project-scoped HS256 JWT signer (backed by @noble/hashes) used for both runtime tokens and Firefox AMO authorization, while keeping existing token formats and improving cache behavior to account for API key changes.

Changes:

  • Introduce signHs256Jwt (HS256-only signing) and migrate runtime + AMO JWT generation off jsonwebtoken.
  • Update runtime token caching to regenerate when the API key changes (not just on expiry) and preserve iat behavior.
  • Remove crypto-browserify build fallback and add/adjust unit tests to verify HS256 signatures and cache behavior.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/unit/utils/jwt-token-generator.test.mjs Replaces jsonwebtoken decode/verify with explicit HS256 verification + adds cache/key-change coverage.
tests/unit/utils/hs256-jwt.test.mjs Adds focused unit tests for the new HS256 JWT signer utility.
tests/unit/release/submit-stores.test.mjs Verifies AMO Authorization JWT structure/signature without jsonwebtoken.
src/utils/jwt-token-generator.mjs Switches runtime token generation to the new signer and extends cache invalidation to include API key changes.
src/utils/hs256-jwt.mjs New HS256 JWT signing helper built on @noble/hashes.
scripts/submit-stores.mjs Migrates AMO JWT creation from jsonwebtoken to the new HS256 signer.
package.json Drops jsonwebtoken/crypto-browserify, adds @noble/hashes, bumps uuid and pre-commit.
package-lock.json Lockfile updates reflecting dependency removals/additions and version bumps.
build.mjs Removes webpack crypto fallback to drop the browser crypto polyfill tree.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/utils/hs256-jwt.mjs
Comment on lines +19 to +22
function signHs256Jwt(payload, secret, header = { alg: 'HS256', typ: 'JWT' }) {
const encodedHeader = encodeJson(header)
const encodedPayload = encodeJson(payload)
const signingInput = `${encodedHeader}.${encodedPayload}`
Comment on lines +7 to +9
function decodeTokenPart(part) {
return JSON.parse(Buffer.from(part, 'base64url').toString('utf8'))
}
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Qodo Logo

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/utils/hs256-jwt.mjs`:
- Around line 19-23: The signHs256Jwt helper should reject missing/invalid
secrets and stop accepting caller-provided JWT algorithms. Update signHs256Jwt
to validate secret before TextEncoder.encode(secret) so undefined/null/empty
values fail fast, and pin the header used by encodeJson to HS256/typ JWT instead
of trusting the header argument. Keep the HMAC-SHA256 signing logic in sync with
the header in signHs256Jwt so runtime tokens and AMO auth always produce
self-consistent JWTs.

In `@src/utils/jwt-token-generator.mjs`:
- Around line 18-29: The cache expiration in jwt-token-generator’s token
creation logic is computed from the millisecond clock, while the JWT payload exp
in the same function is based on whole seconds, so align the cache cutoff to the
same rounded seconds boundary used for exp. Update the token creation flow in
jwt-token-generator.mjs so tokenExpiration is derived from the same
currentSeconds/exp basis as jwtToken generation, ensuring getToken() stops
reusing a token as soon as its JWT is considered expired.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 08e8fd43-80d9-4db7-b50f-3f08c7d1303f

📥 Commits

Reviewing files that changed from the base of the PR and between ff3d5f7 and b3d8480.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • build.mjs
  • package.json
  • scripts/submit-stores.mjs
  • src/utils/hs256-jwt.mjs
  • src/utils/jwt-token-generator.mjs
  • tests/unit/release/submit-stores.test.mjs
  • tests/unit/utils/hs256-jwt.test.mjs
  • tests/unit/utils/jwt-token-generator.test.mjs
💤 Files with no reviewable changes (1)
  • build.mjs

Comment thread src/utils/hs256-jwt.mjs
Comment on lines +19 to +23
function signHs256Jwt(payload, secret, header = { alg: 'HS256', typ: 'JWT' }) {
const encodedHeader = encodeJson(header)
const encodedPayload = encodeJson(payload)
const signingInput = `${encodedHeader}.${encodedPayload}`
const signature = hmac(sha256, textEncoder.encode(secret), textEncoder.encode(signingInput))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject invalid secrets and pin the header to HS256.

Line 20 lets callers advertise any alg, but Line 23 always signs with HMAC-SHA256, so this helper can generate self-inconsistent JWTs. Also, TextEncoder.encode(secret) string-coerces undefined/null, which means a missing secret now signs with 'undefined' instead of failing fast. Since this is the new shared signer for runtime tokens and AMO auth, both cases turn configuration mistakes into hard-to-diagnose auth failures.

Proposed fix
-function signHs256Jwt(payload, secret, header = { alg: 'HS256', typ: 'JWT' }) {
-  const encodedHeader = encodeJson(header)
+function signHs256Jwt(payload, secret, header = {}) {
+  if (typeof secret !== 'string' || secret.length === 0) {
+    throw new TypeError('JWT secret must be a non-empty string')
+  }
+  if (header.alg && header.alg !== 'HS256') {
+    throw new Error('signHs256Jwt only supports HS256')
+  }
+
+  const encodedHeader = encodeJson({ ...header, alg: 'HS256', typ: 'JWT' })
   const encodedPayload = encodeJson(payload)
   const signingInput = `${encodedHeader}.${encodedPayload}`
   const signature = hmac(sha256, textEncoder.encode(secret), textEncoder.encode(signingInput))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function signHs256Jwt(payload, secret, header = { alg: 'HS256', typ: 'JWT' }) {
const encodedHeader = encodeJson(header)
const encodedPayload = encodeJson(payload)
const signingInput = `${encodedHeader}.${encodedPayload}`
const signature = hmac(sha256, textEncoder.encode(secret), textEncoder.encode(signingInput))
function signHs256Jwt(payload, secret, header = {}) {
if (typeof secret !== 'string' || secret.length === 0) {
throw new TypeError('JWT secret must be a non-empty string')
}
if (header.alg && header.alg !== 'HS256') {
throw new Error('signHs256Jwt only supports HS256')
}
const encodedHeader = encodeJson({ ...header, alg: 'HS256', typ: 'JWT' })
const encodedPayload = encodeJson(payload)
const signingInput = `${encodedHeader}.${encodedPayload}`
const signature = hmac(sha256, textEncoder.encode(secret), textEncoder.encode(signingInput))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils/hs256-jwt.mjs` around lines 19 - 23, The signHs256Jwt helper should
reject missing/invalid secrets and stop accepting caller-provided JWT
algorithms. Update signHs256Jwt to validate secret before
TextEncoder.encode(secret) so undefined/null/empty values fail fast, and pin the
header used by encodeJson to HS256/typ JWT instead of trusting the header
argument. Keep the HMAC-SHA256 signing logic in sync with the header in
signHs256Jwt so runtime tokens and AMO auth always produce self-consistent JWTs.

Comment on lines 18 to 29
exp: currentSeconds + timeoutSeconds,
iat: currentSeconds,
timestamp: currentSeconds,
}

jwtToken = jwt.sign(payload, secret, {
header: {
alg: 'HS256',
typ: 'JWT',
sign_type: 'SIGN',
},
jwtToken = signHs256Jwt(payload, secret, {
alg: 'HS256',
typ: 'JWT',
sign_type: 'SIGN',
})
tokenApiKey = apiKey
tokenExpiration = ms + timeoutSeconds * 1000

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Align the cache cutoff with the JWT exp.

Line 29 derives tokenExpiration from the original millisecond clock, while Line 18 rounds exp down to whole seconds. That leaves a 0-999 ms window where getToken() can reuse a token whose JWT is already expired, which can show up as intermittent 401s at the cache boundary.

Proposed fix
   const payload = {
     api_key: id,
     exp: currentSeconds + timeoutSeconds,
     iat: currentSeconds,
     timestamp: currentSeconds,
   }

   jwtToken = signHs256Jwt(payload, secret, {
     alg: 'HS256',
     typ: 'JWT',
     sign_type: 'SIGN',
   })
   tokenApiKey = apiKey
-  tokenExpiration = ms + timeoutSeconds * 1000
+  tokenExpiration = payload.exp * 1000
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
exp: currentSeconds + timeoutSeconds,
iat: currentSeconds,
timestamp: currentSeconds,
}
jwtToken = jwt.sign(payload, secret, {
header: {
alg: 'HS256',
typ: 'JWT',
sign_type: 'SIGN',
},
jwtToken = signHs256Jwt(payload, secret, {
alg: 'HS256',
typ: 'JWT',
sign_type: 'SIGN',
})
tokenApiKey = apiKey
tokenExpiration = ms + timeoutSeconds * 1000
exp: currentSeconds + timeoutSeconds,
iat: currentSeconds,
timestamp: currentSeconds,
}
jwtToken = signHs256Jwt(payload, secret, {
alg: 'HS256',
typ: 'JWT',
sign_type: 'SIGN',
})
tokenApiKey = apiKey
tokenExpiration = payload.exp * 1000
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils/jwt-token-generator.mjs` around lines 18 - 29, The cache expiration
in jwt-token-generator’s token creation logic is computed from the millisecond
clock, while the JWT payload exp in the same function is based on whole seconds,
so align the cache cutoff to the same rounded seconds boundary used for exp.
Update the token creation flow in jwt-token-generator.mjs so tokenExpiration is
derived from the same currentSeconds/exp basis as jwtToken generation, ensuring
getToken() stops reusing a token as soon as its JWT is considered expired.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants