[ ] Regression
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
export class AuthModule implements NestModule {
public configure(consumer: MiddlewaresConsumer) {
consumer
.apply(passport.authenticate('jwt', { session: false }))
.forRoutes({ path: '/auth/authorized', method: RequestMethod.ALL });
}
}
Get routes to apply middleware by decorator.
export class AuthModule implements NestModule {
public configure(consumer: MiddlewaresConsumer) {
consumer
.apply(passport.authenticate('jwt', { session: false }))
.forRoutes()
.with(Authorize);
}
}
import { Controller, Post, HttpStatus, HttpCode, Get } from '@nestjs/common';
import { AuthService } from './auth.service';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Post('token')
@HttpCode(HttpStatus.OK)
public async getToken() {
return await this.authService.createToken();
}
@Get()
@Authorize()
public async authorized() {
console.log('Authorized route...');
}
}
N/A
this way it is much simpler to apply middleware to a collection of routes with a specific decorator.
Otherwise it is much more readable and easy to identify if the route needs authentication or not.
Nest version: 4.4.0
For Tooling issues:
- Node version: 8.9.1
- Platform: Windows
Others:
This can be achieved with the new decorator added here: https://github.com/nestjs/nest/pull/240
Simply make this decorator return a boolean of whether or not the request is authorized.
With this approach the request arrives in controller action.
If we use middleware we can stop request before to arrive in controller.
I don't know if I'm correct.
@nicolastakashi in this case you need to use guards
@zMotivat0r If I use guards I can't use passport.apply
@nicolastakashi why not? 馃檪 guards have an access to the request
, which has a res
property. Pass custom callback and use next()
as a resolve
function of the promisified callback.
@kamilmysliwiec I do that, looks like good. But the callback never is fired.
@Guard()
export class AuthGuard implements CanActivate {
canActivate(dataOrRequest, context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
return new Promise<boolean>((resolve, reject) => {
passport.authenticate('jwt', function (args) {
return resolve(true);
})
});
}
}
@nicolastakashi passport.authenticate()
returns a function that you have to call 馃檪 (it accepts req, res and next)
@kamilmysliwiec sorry budy.
I don't understand. Can you send me a example.
As far as I remember it should be sth like this:
passport.authenticate('jwt', function (args) {
return resolve(true);
})(req, res, next);
I try to do this.
But the callback never is resolved.
So there's a missing (req, res, next);
in what you have sent before.
@kamilmysliwiec It's works.
But I found some problems, If I don't pass token in header it keep working such as authorized user.
And callback params is always null.
and If a return false I just can get 403 and not a 401
Your custom callback accepts several params. Take a look at passport docs, there should be a err
and info
argument. :) In the Nest docs there's a solution how to change the default guard behaviour (just throw HttpException
exception instead of returning false value)
I'm so sorry man.
I had not noticed the part where it talks to throw an httpexception
I will try it.
Thank you for now
@kamilmysliwiec
I wrote this code:
import { Guard, CanActivate, ExecutionContext, UnauthorizedException, HttpException, HttpStatus } from '@nestjs/common';
import { Observable } from 'rxjs/Observable';
import * as passport from 'passport';
@Guard()
export class AuthGuard implements CanActivate {
async canActivate(dataOrRequest, context: ExecutionContext): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
passport.authenticate('jwt', { session: false }, function (args) {
if (args != 200) throw new UnauthorizedException();
return resolve(true);
})(dataOrRequest.res.req, dataOrRequest.res, dataOrRequest.nex);
});
}
}
Works like a charm.
So I create a Exception Filter, But I can't filter this and I get this message in console.
(node:8512) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): #<HttpException>
(node:8512) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Any Idea?
I think that comes from throw. Try using reject instead?
@wbhob rect does't work because promise is a a boolean.
@Guard()
export class AuthGuard implements CanActivate {
async canActivate(dataOrRequest, context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
const isAuthenticated = await new Promise<boolean>((resolve, reject) => {
passport.authenticate('jwt', { session: false }, (args) => {
if (args != 200) {
return resolve(false);
}
return resolve(true);
})(dataOrRequest.res.req, dataOrRequest.res, dataOrRequest.nex);
});
if (!isAuthenticated) {
throw new HttpException('', HttpStatus.UNAUTHORIZED);
}
return true;
}
}
all it took for me
@Get('user')
@UseGuards(PassportAuthGuard)
public async user(@Req() req) {
return req.user;
}
@Injectable()
export class PassportAuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const req = context.switchToHttp().getRequest();
if (!req.isAuthenticated()) {
throw new UnauthorizedException();
}
return true;
}
}
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment