Passport.js local and JWT strategies: verify callback argument consistency
0 reputation · 18 Mar 2024, 05:29 UTC
0 reputation · 18 Mar 2024, 05:29 UTC
The goal is to clarify whether the verify callback supplied to a Passport.js strategy must always receive three arguments (err, user, info) or may receive only two arguments (err, user) when the strategy does not generate an info object.
Current Passport documentation leaves this behavior unspecified, and individual strategies such as passport-local and passport-jwt exhibit different expectations, leading to potential mismatches when developers write a single verify function intended to work across multiple strategies.
Should Passport.js normalize the callback so that info is always present (possibly undefined) for all strategies? Or should each strategy be allowed to omit info and rely on the developer to handle a two‑argument signature? How can developers write a verify function that remains compatible with both passport-local and passport-jwt without conditional argument checks?
30775 reputation · 18 Mar 2024, 16:30 UTC
Passport.js does not enforce a fixed number of arguments for the done callback that a strategy’s verify function must invoke. In practice, the callback is called with either two arguments (err, user) or three arguments (err, user, info). Both passport-local and passport-jwt accept the third info argument, but most examples call done with only two arguments when no additional information is needed.
Strategies differ in the parameters they pass to verify:
(username, password, done)(jwt_payload, done)Regardless of those input parameters, the done callback that you invoke inside verify follows the same contract: done(err, user, info?). If you omit info, Passport simply receives undefined for that slot.
done with three arguments: done(null, user, null) when you have no info to return. This guarantees that the info slot is defined for every strategy.done(null, user, {role: 'admin'}).passport.authenticate()), treat info as optional: function(req, res, next) { /* info may be undefined */ }.verify implementation, keep its signature generic: function verify(...args) { const done = args.pop(); /* args[0] and args[1] are strategy‑specific */ done(null, user, null); }.
By always supplying the third argument, you avoid conditional logic that checks arguments.length in downstream code. The Passport core and the community libraries treat a missing info the same as undefined, so the explicit null value is harmless and fully compatible.
Some older or custom strategies may not construct the info object at all, even when you pass it. Inspect the strategy’s verify implementation or its README to confirm whether it ever populates info. If you find a strategy that never uses the third argument, the explicit null call above remains safe.
If your application uses a third‑party strategy that you suspect might behave differently, let us know the strategy name and version. That way we can confirm whether it expects a three‑argument done call or not.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.