В настоящее время я внедряю аутентификацию JWT с помощью Passport.js в приложение NestJS.
В некоторых из моих распознавателей GraphQL мне нужен доступ к аутентифицированному пользователю.Я знаю, что аттестат присоединит аутентифицированного пользователя к объекту запроса (по крайней мере, я надеюсь, что это правильно), но я не знаю, как получить доступ к объекту запроса внутри распознавателя.
Я следовал за проблемой https://github.com/nestjs/nest/issues/1326 и упомянутой ссылкой https://github.com/ForetagInc/fullstack-boilerplate/tree/master/apps/api/src/app/auth внутри номера.Я видел некоторый код, который использует @Res() res: Request
в качестве параметра метода в методах распознавания GraphQL, но я всегда получаю undefined
для res
.
Это текущие реализации, которые у меня есть:
GQLAuth
import { Injectable, ExecutionContext } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { GqlExecutionContext } from '@nestjs/graphql';
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context-host';
import { AuthenticationError } from 'apollo-server-core';
@Injectable()
export class GqlAuthGuard extends AuthGuard('jwt') {
canActivate(context: ExecutionContext) {
const ctx = GqlExecutionContext.create(context);
const { req } = ctx.getContext();
console.log(req);
return super.canActivate(new ExecutionContextHost([req]));
}
handleRequest(err: any, user: any) {
if (err || !user) {
throw err || new AuthenticationError('GqlAuthGuard');
}
return user;
}
}
Resolver, которому требуется доступ к текущему пользователю
import { UseGuards, Req } from '@nestjs/common';
import { Resolver, Query, Args, Mutation, Context } from '@nestjs/graphql';
import { Request } from 'express';
import { UserService } from './user.service';
import { User } from './models/user.entity';
import { GqlAuthGuard } from '../auth/guards/gql-auth.guard';
@Resolver(of => User)
export class UserResolver {
constructor(private userService: UserService) {}
@Query(returns => User)
@UseGuards(GqlAuthGuard)
whoami(@Req() req: Request) {
console.log(req);
return this.userService.findByUsername('aw');
}
}
Стратегия JWT
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { AuthService } from './auth.service';
import { JwtPayload } from './interfaces/jwt-payload.interface';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(private readonly authService: AuthService) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: process.env.SECRET,
});
}
async validate(payload: JwtPayload) {
const user = await this.authService.validateUser(payload);
if (!user) {
throw new UnauthorizedException();
}
return user;
}
}
Авторизация и создание токенов JWT работает отлично.GraphQL guard также отлично работает для методов, которым не требуется доступ к пользователю.Но для методов, которым нужен доступ к аутентифицированному пользователю, я не вижу способа его получить.
Есть ли способ сделать что-то подобное?