0
votes

When using Passport with Express, Typescript thinks req.user is possibly undefined inside a route when using an auth middleware. When using an auth middleware, I'd like req.user to be defined in all cases because otherwise, the middleware will return 401 unauthorized response.

If the route is using an auth middleware like this:

app.use( '/users', passport.authenticate('bearer', { session: false }), usersRouter ); 

The routes within /users shouldn't have the user being possibly undefined since it never will be.

How does one achieve this, without declaring a custom request interface to use for each route?

1
Could you give a minimal reproducible example - where are you expecting the middleware to change the type of the request object in the handler? - jonrsharpe
If the route is using an auth middleware like this: app.use( '/users', passport.authenticate('bearer', { session: false }), usersRouter ); The routes within /users shouldn't have the user being possibly undefined since it never will be. - Gunnar Torfi Steinarsson
And how is that supposed to change the type of the userRouter or the request? The router type isn't defined by where it's used. - jonrsharpe
That's what my question is about, I'm not sure how that's implemented but I'm curious if it is possible. Otherwise, do I have to do something like if (!req.user) return res.status(401).send() at the top of every single route? - Gunnar Torfi Steinarsson
You can extend the Express namespace's Request interface in the same way that library does, making the user non-optional, but then it can't warn you on routes that aren't authenticated. - jonrsharpe

1 Answers

0
votes

In short, you cannot make Typescript understand whether your middleware set req.user or not as TS doesn't "understands" how middlewares work in Express. However, you can extend the request interface and use your custom implementation where you know the value is set (aka in the authenticated routes).

Defining the custom interface:

import { Request } from 'express';
import { YourUserDefinitionInterface } from './your-user-definition.interface.ts';

export interface AuthenticatedRequest extends Request {
  user: YourUserDefinitionInterface 
}

Using it in a route:

// The below route is behind the auth middleware
app.get('/some-path', (req: AuthenticatedRequest) => {
  // Your handling logic here
});