feathers
feathers copied to clipboard
Multiple auth services - wrong service is used to look for header
Steps to reproduce
In our app, we have two authentication services for two "arms" of the app. This works fine for the most part, but we have a special case where we have to augment the initial finding of the JWT from the inbound payload. (We were using the same header field "Authorization" for clients of both services, but with different tokens etc.)
What we want to do is, in parse, make a contextual decision on where to also possibly look for a token (in our case, in a payload field inside the request). So, we create instances of our subclassed JWTStrategy (which implements parse) for both our services. So authService A has a MyJWTStrategy() and authService B has a MyJWTStrategy(). However, we'd never see matches from the parse inside the strategies in authService B.
Thinking it was a naming problem I tried something different and decided to use different header names in the client and server config. Figure it wouldn't find one but would keep going until it did. Didn't work. Went further and made sure to define both JWT services with different names vs jwt.
Fundamentally, the problem lies in https://github.com/feathersjs/feathers/blob/3215714766f047cc9526f260796467b3c52f8d15/packages/express/lib/authentication.js#L13 where the list of strategies is passed for parsing.
This only uses the defaultAuthentication, but the problem is that different routes use different authentication services. Is there a way to have the parsing influenced by which auth service is "allowed" for that service call? I realize it has to happen early in the flow, but when I call authenticate({ service:..., strategies: ...}) in my before hooks, I would assume that only the strategies for that service are used for header parsing and not the parsers for the defaultService.
If anything, I'd expect ALL parsers for all strategies for ALL services get called until a valid payload was found, but half of my registered strategies (all those on authService B) are never called.
Expected behavior
Magical rainbows and the parsers for the authService that goes with the route are used (and ideally lazily at the point of the authenticate hook running.)
Actual behavior
Only the strategies registered on the first auth service are used.
System configuration
Module versions (especially the part that's not working): 4.5.2
NodeJS version: 12.16.1
Operating System: macos catalina
Although it is not documented you should be able to use the parseAuthentication middleware again on the route you want to override the service for:
app.configure(express.rest());
// ...
app.use('/v1/*', express.parseAuthentication({
service: '/v1/authentication'
}));
// ...
app.configure(services);
Sounds similar to my issue #1415
While revisiting my code to convert to typescript, the typing for express.parseAuthentication in index.d.ts (v4.5.11) in the distributed package shows up as:
parseAuthentication (...strategies: string[]): express.RequestHandler
instead of the actual definition in the typescript source
https://github.com/feathersjs/feathers/blob/6c972f0a8faf2397c40e89f4d760653cb7bf5204/packages/express/src/authentication.ts#L17
So I had to cast my options to any to make it work.