Skip to content

Fix #1000: Prevent callback from being called twice on payload claim conflict#1011

Open
cobyfrombrooklyn-bot wants to merge 1 commit intoauth0:masterfrom
cobyfrombrooklyn-bot:fix-issue-1000
Open

Fix #1000: Prevent callback from being called twice on payload claim conflict#1011
cobyfrombrooklyn-bot wants to merge 1 commit intoauth0:masterfrom
cobyfrombrooklyn-bot:fix-issue-1000

Conversation

@cobyfrombrooklyn-bot
Copy link

When jwt.sign() is called with a callback and the payload has a claim that conflicts with an option (e.g., payload.iss + options.issuer), the callback was invoked twice: once with the error and once with a successfully signed token.

Root Cause

The options-to-payload mapping at line 217 used forEach(). Inside the forEach callback, return failure() only returns from the forEach callback function, not from the outer sign function. So after the error callback fires, the forEach continues processing remaining keys, and then execution falls through to jws.createSign() which calls the callback again with a token.

Fix

Replaced forEach with a for loop so that return failure() properly exits the sign function, preventing the signing logic from executing after an error.

Test

Added test in async_sign.tests.js: "should call the callback only once with an error". It:

  1. Signs a token with conflicting iss in payload and issuer in options
  2. Counts callback invocations
  3. Asserts callback is called exactly once, with an error
  4. Uses setTimeout to verify no second invocation occurs

Without the fix, the callback fires twice (error + token). With the fix, it fires once (error only).

Full test suite: 512 passing, 1 pending. Tested locally on macOS ARM (Apple Silicon).

Fixes #1000

When jwt.sign() was called with a callback and the payload had a
claim that conflicted with an option (e.g., payload.iss + options.issuer),
the callback was invoked twice: once with the error and once with
a signed token.

This happened because the options-to-payload mapping used forEach(),
where 'return failure()' only returned from the forEach callback,
not from the outer function. Execution continued to jws.createSign().

Replaced forEach with a for loop so 'return failure()' properly
exits the sign function.

Fixes auth0#1000
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.

jwt.sign() callback is executed twice for "The payload already has an "..." property" errors

1 participant