fix(sign): prevent double callback when payload already has a property #1002
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
By submitting a PR to this repository, you agree to the terms within the Auth0 Code of Conduct. Please see the contributing guidelines for how to create and submit a high-quality PR for this repo.
Description
This PR fixes a bug in jwt.sign() where the callback is called twice when the payload already contains a property that conflicts with options. For example, when payload.iss exists and options.issuer is also provided, the callback was triggered once with an error and then again with a token.
The root cause was that Object.keys(options_to_payload).forEach(...) with return failure(err) only returned from the callback, not the parent function, allowing the signing logic to continue and call the callback a second time.
Solution:
Replaced .forEach() with a for...of loop so return failure(err) exits the sign() function immediately.
Added a regression test to ensure the callback is called only once in conflict scenarios.
No breaking changes to the API.
References
Fixes GitHub issue: #1000
Added a regression test in test/callback-issue.test.js:
const assert = require('assert');
const jwt = require('../index.js');
describe('jwt.sign callback fix', function () {
it('should call callback only once on payload/options conflict', function (done) {
let callbackCount = 0;
});
});
All existing tests pass.
Regression test verifies callback is called only once.
Developed and tested in Node.js v22.19.0 on Linux (WSL/Debian).
This change adds test coverage for the fixed functionality.
Checklist
I have added tests for the fixed functionality
All active GitHub checks for tests, formatting, and security are passing
The correct base branch is being used (master).