Secret function is called with different signature depending on context
- Dominant language
- JavaScript
- Stars
- 586
- Forks
- 120
- PR merge metrics
- No merged PRs in 30d
Description
### Prerequisites
- [x] I have written a descriptive issue title
- [x] I have searched existing issues to ensure the bug has not already been reported
### Fastify version
5.x.x
### Plugin version
10.x.x
### Node.js version
24.x
### Operating system
macOS
### Operating system version (i.e. 20.04, 11.3, 10)
26.3
### Description
fastify-jwt allows the `secret` plugin option to be a function instead of a static string.
The documentation states that the function will receive request, token, and callback as input.
This works correctly when called from the request or reply context, i.e.
```js
request.jwtVerify()
```
However, verify can be called on the fastify instance outside of a request context too:
```js
fastify.jwt.verify('example token')
```
When this is done, and a function was passed as `secret` option, i.e.
```js
const fastify = require('fastify')()
fastify.register(require('@fastify/jwt'), {
secret: function randomSecret(request, token, callback) {
console.log(request)
callback(null, 'random token')
}
})
```
Then the secret function will be called with the decoded token as first parameter, instead of the fastify request object.
This is happening because in the verify implementation on the fastify instance, the secret option is never treated as a function, and it's passed as is to the the fast-jwt verifier as key.
The verifier itself does support key to be function, but indeed with its own signature.
Whilst this is not a bug per se, I'd say it's an inconsistent or surprising behavior that might cause bugs in consumer code - and might be worth clarifying and uniform it.
PS: this was found whilst investigating the following issue on https://github.com/nearform/fastify-jwt-jwks/issues/54
### Link to code that reproduces the bug
https://github.com/paolochiodi/fastify-jwt-secret-as-function-repro
### Expected Behavior
The documentation seems to be saying that the function version of the secret is only supported in requests context, but it's easy to miss:
> Function based secret is supported by the request.jwtVerify() and reply.jwtSign() methods and is called with request, token, and callback parameters.
I'd suggest a few possible resolutions (from more desirable to less desirable, imo):
1. Calls to secret function are uniformed and happen with a consistent, documented signature
2. Differences are documented clearly, so consumers are made aware of the scenario
3. secret option as function is prohibited and guarded against when using verify on the fastify instance (i.e. throwing an error).
Contributor guide
Assessment
This issue has not been assessed yet.