New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(@nestjs/passport): support graphql context in auth guard #341
base: master
Are you sure you want to change the base?
Conversation
'@nestjs/graphql', | ||
'AuthGuard' | ||
); | ||
return GqlExecutionContext.create(context).getContext().req; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if someone has a different value than req
for the context? Like with Fastify the property is request
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Didn't know that Fastify adapter uses different properties. Right now i don't have any good ideas on how to sole this issue. Also there are some other adapters, and their properties may be different too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this depends on platform. Doesn't getContext()
return the context provided to the GraphQLModule
/ApolloServer
constructor (docs)? So it would depend on how people initialize the context, e.g.
GraphQLModule.forRoot({
context: ({ req }) => {
return {
foo: 'bar',
contextRequest: req,
}
}
})
Maybe a better solution is to make this more first class; e.g.
Maybe override the constructor to store the request
class GqlExecutionContext {
constructor(readonly private originalContext: ExecutionContext, ...) {
super(...)
}
static create(context: ExecutionContext) {
...
new GqlExecutionContext(context, ...)
}
getRequest<T = any>() {
return this.originalContext.switchToHttp().getRequest()
}
}
or something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the same docs you linked
The fields of the object passed to your context function differ if you're using middleware besides Express. See the API reference for details..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 still, this assumes that someone set up the context
key correctly and wouldn't account for someone using the snippet I posted above. Nothing wrong with it; it would just require documentation (admittedly, the workaround we have to do because of this problem should have also been documented)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is current documentation on using Passport with GraphQL, though it still is also only valid for working with Express (as at the time of writing the docs, apollo-server-fastify
wasn't compatible). Now when setting the context for fastify, the context should be
context({ request, reply}) => ({ request, reply })
The snippet above looks promising, but I would have to check how well context.switchToHttp().getRequest()
works on a GQL request in the first place, as the arguments for HTTP and GQL are different.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jmcdo29 we should be able to fix this on the @nestjs/graphql
level, here https://github.com/nestjs/graphql/blob/master/lib/utils/merge-defaults.util.ts#L9
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
When adding AuthGuard to graphql resolver class/method you have to add custom logic for resolving the request object as described in Nest.js documentation https://docs.nestjs.com/techniques/authentication#graphql.
For example, to create a guard that would support both HTTP and GraphQL contexts you have to write something like this (the code is taken from one of my projects where both REST and GraphQL APIs should be supported):
which works just perfect. But it is a boilerplate.
What is the new behavior?
Now, with the built-in check for graphql context type and request object resolving logic, users will not have to write boilerplate code in each guard.
Does this PR introduce a breaking change?
Other information