Reputation: 23
we have a NestJS GraphQL server running and we are trying to set an httpOnly cookie in an interceptor.
The set seems to work if we call the mutation by Postman, showing the cookie in the cookies tab.
But calling the mutation from the Playground, there is no trace of the cookie in the browser.
Even accessing the request.cookies
property in a guard gives us no results. What are we doing wrong?
The server is fastify
based and we are using fastify-cookie
library to set the cookie.
The interceptor code is:
@Injectable()
export class AccessTokenCookieInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler<AccessTokens>): Observable<any> {
const ctx = GqlExecutionContext.create(context);
const response: FastifyReply = ctx.getContext().response;
return next.handle().pipe(
tap(data => {
response.setCookie('my_cookie', JSON.stringify(data), {
httpOnly: true,
path: '/',
});
}),
);
}
}
The GQLModule:
GraphQLModule.forRoot({
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
sortSchema: true,
context: ({ request, reply }) => {
return {
request,
response: reply,
};
},
...
}),
The guard where we read the cookie:
@Injectable()
export class AccessTokenGuard implements CanActivate {
async canActivate(context: ExecutionContext): Promise<boolean> {
const ctx = GqlExecutionContext.create(context);
const request = ctx.getContext().request;
const cookie = request.cookies['my_cookie'];
const tokens: AccessTokens = JSON.parse(cookie);
request.finxTokens = tokens;
return true;
}
}
Thank you for your help!
Upvotes: 2
Views: 4702
Reputation: 21
This worked for me. Add below code in class GqlAuthGuard extends AuthGuard('local')
handleRequest(err, user, info, context) {
if (err || !user || info) throw err || new UnauthorizedException();
const accessToken = this.jwtService.sign({ ... });
const gqlExecutionContext = GqlExecutionContext.create(context);
const request = gqlExecutionContext.getContext().req;
request.res?.cookie('access_token', accessToken);
return user;
}
Upvotes: 0
Reputation: 191
1 - You need to add cors
settings to your GQLModule;
GraphQLModule.forRoot({
...
cors: {
credentials: true,
origin: true
}
})
2 - In your apollo client settings to tell your network interface to send the cookie along with every request. You just need to pass the credentials
option;
const httpLink = new HttpLink({ uri: 'graphql', credentials: 'include' });
Upvotes: 4