NestJS在通过JWT认证的GraphQL解析器中获取当前用户 [英] NestJS Get current user in GraphQL resolver authenticated with JWT
问题描述
我目前正在将Passport.js的JWT身份验证实现到NestJS应用程序中.
I am currently implementing JWT authentication with Passport.js into a NestJS application.
在我的一些GraphQL解析器中,我需要访问当前经过身份验证的用户.我知道通行证会将经过身份验证的用户附加到请求对象(至少我希望这是正确的),但是我不知道如何访问解析器中的请求对象.
In some of my GraphQL resolvers I need to access the currently authenticated user. I know that passport will attach the authenticated user to the request object (at least I hope that this is correct), but I do not know how to access the request object inside a resolver.
我关注了这个问题 https://github.com/nestjs/nest/issues/1326 和提到的链接 https://问题内的github.com/ForetagInc/fullstack-boilerplate/tree/master/apps/api/src/app/auth .我在GraphQL解析器方法中看到一些使用@Res() res: Request
作为方法参数的代码,但是对于res
,我总是得到undefined
.
I followed the issue https://github.com/nestjs/nest/issues/1326 and the mentioned link https://github.com/ForetagInc/fullstack-boilerplate/tree/master/apps/api/src/app/auth inside the issue. I saw some code that uses @Res() res: Request
as a method parameter in the GraphQL resolver methods, but I always get undefined
for res
.
这些是我目前拥有的实现:
These are the current implementations I have:
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;
}
}
需要访问当前用户的解析器
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');
}
}
智威汤逊策略
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保护也可以很好地用于不需要访问用户的方法.但是对于需要访问当前经过身份验证的用户的方法,我看不到获得它的方法.
Authorization and creating JWT tokens works fine. GraphQL guard also works fine for methods that do not need to access the user. But for methods that need access to the currently authenticated user, I see no way of getting it.
有没有办法完成这样的事情?
Is there a way to accomplish something like this ?
推荐答案
最终找到了答案... https://github.com/nestjs/graphql/issues/48#issuecomment-420693225 为我指明了创建用户装饰器
Finally found the answer ... https://github.com/nestjs/graphql/issues/48#issuecomment-420693225 pointed me into the right direction of creating a user decorator
// user.decorator.ts
import { createParamDecorator } from '@nestjs/common';
export const CurrentUser = createParamDecorator(
(data, req) => req.user,
);
然后在我的解析器方法中使用它:
And then use this in my resolver method:
import { User as CurrentUser } from './user.decorator';
@Query(returns => User)
@UseGuards(GqlAuthGuard)
whoami(@CurrentUser() user: User) {
console.log(user);
return this.userService.findByUsername(user.username);
}
现在一切正常.因此,此答案的全部功劳归于 https://github.com/cschroeter
Now everything works as expected. So all credits of this answer goes to https://github.com/cschroeter
这篇关于NestJS在通过JWT认证的GraphQL解析器中获取当前用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!