what is the difference between AuthGuard('local') and PassportStrategy(Strategy,'local')

728 Views Asked by At

if i can use: "export class LocalStrategy extends PassportStrategy(Strategy,'local') {}" why is necessary or why do i need to create: "export class LocalAuthGuard extends AuthGuard('local') {}"

i was using in Controller guards like both of them i mentioned above but when i use in controller :

"@UseGuards(AuthGuard('local'))" 

it calls only PassportStrategy class

and when i use in controller like this: @UseGuards(LocalAuthGuard) it is executed both of them like:

"class LocalStrategy extends PassportStrategy(Strategy,'local') {"

and

"class LocalAuthGuard extends AuthGuard('local') {"

can someone please help me to understand this?? and what is a best practice

1

There are 1 best solutions below

0
Jay McDoniel On

if i can use: export class LocalStrategy extends PassportStrategy(Strategy,'local') {} why is necessary or why do i need to create: export class LocalAuthGuard extends AuthGuard('local') {}

That's just the thing, you don't have to create the LocalAuthGuard. You really should only create it if you

  1. Don't want to have to continually use a string to remember what strategy you're using
  2. Want to add custom logic to how the guard works

I think generally you're unaware of what is being called and how it's being called here. So, the PassportStrategy class is used to configure the passport middleware for a sepcific strategy type (in this case the strategy from passport-local which takes in username and password from the request body and calls them through validate (actually verify in passport's code)). The AuthGuard() is how Nest abstracts the call to passport.use('strategy', (req, res, next)) so that it fits better into the context of Nest.

Normally when we use passport with express it looks like

passport.use(new LocalStrategy(function verify(username, password, done) {
  const user = getUserFromDb(username);
  if (!user) {
    done(new Error('Incorrect username or password'));
    return;
  }
  if (user.password !== password) {
    done(new Error('Incorrect username or password'));
    return;
  }
  done(null, user);
  return;
}));

app.get('/some/route', passport.authenticate('local'), (req, res, next) => {
  res.send('Some protected data');
  return;
});

This doesn't really fit into Nest's syntax and approach though using decorators to define the routes and not having middleware addable directly to the route handler.

So instead, Nest provides us the PassportStrategy mixin, which ends up calling passport.use(new Strategy(this.validate.bind(this)) (or very similar) under the hood, so that passport gets configured and is aware of the strategy and how to use it without us having to gunk up the main.ts.

Now, AuthGuard() takes in a strategy name and returns a guard class. This is a mixin as well, which is a function that returns a class. This guard has it's own canActivate and ends up calling to passport.authenticate(strategy) for us, and handles the response that comes from passport, either allowing the guard to return true and move on, or Nest will throw new UnathorizedException() for us, to return a 401.

Whether you use class LocalAuthGuard extends AuthGuard('local') or AuthGuard('local'), the same thing is happening with regards to passport and the LocalStrategy that extends the passport strategy class.

This article does a deep dive on passport and Nest in the first half if you'd like to go into a bit more depth