[ ] 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.
@UseGuards(), @UseInterceptors and middleware do not work with @Subscription().
Example:
@Injectable()
export class CatsGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
console.log('Guard');
const ctx = GqlExecutionContext.create(context);
return true;
}
}
@Injectable()
export class AuthInterceptor implements NestInterceptor {
constructor() {}
public async intercept(
context: ExecutionContext,
call$: Observable<any>,
): Promise<Observable<any>> {
console.log(`AuthInterceptor`);
return call$;
}
}
@Subscription('catCreated')
@UseGuards(CatsGuard)
@UseInterceptors(AuthInterceptor)
catCreated() {
return {
subscribe: () => {
console.log('Subscription');
return pubSub.asyncIterator('catCreated');
},
};
}
After subscription only Subscription will be logged into console.
There should be middleware to work with graphQL subscriptions.
I took 12-graphql-apollo sample and added the code from above.
https://github.com/nestjs/nest/tree/master/sample/12-graphql-apollo
Using authorization middleware with subscriptions looks impossible right now.
Nest version: 5.3.6
For Tooling issues:
- Platform: Mac
Others:
What you can do to protect your GraphQL subscription endpoint is this:
GraphQLModule.forRoot({
typePaths: ['./**/*.graphql'],
installSubscriptionHandlers: true,
context: ({ req }) => ({ req }),
subscriptions: {
onConnect: connectionParams => {
// all keys to lowercase
connectionParams = mapKeys(connectionParams, (value: String, key: String) => key.toLowerCase());
// get `authroization` header
const authToken = get(connectionParams, 'authorization', null);
if (authToken) {
return this.jwtService.verify(authToken.split(' ')[1]);
}
throw new AuthenticationError('authToken must be provided');
}
}
});
@cschroeter While guards/interceptors don't work with subscriptions it seems to be the best solution. Thanks!
@cschroeter how would you close operations after connection when the token has expired?
Why cannot guards/interceptors work with subscriptions?
What you can do to protect your GraphQL subscription endpoint is this:
GraphQLModule.forRoot({ typePaths: ['./**/*.graphql'], installSubscriptionHandlers: true, context: ({ req }) => ({ req }), subscriptions: { onConnect: connectionParams => { // all keys to lowercase connectionParams = mapKeys(connectionParams, (value: String, key: String) => key.toLowerCase()); // get `authroization` header const authToken = get(connectionParams, 'authorization', null); if (authToken) { return this.jwtService.verify(authToken.split(' ')[1]); } throw new AuthenticationError('authToken must be provided'); } } });
I've just been using nestjs for a while, and I want to know how this jwtService was injected under this forRoot.
@limwcj have you found a way to inject the service ?
@hxdef2517 use GraphQLModule.forRootAsync
@bcba25 I post how I get it here Document how authentication guards for GraphQL Subscriptions work
GraphQLModule.forRootAsync({
imports: [AuthModule],
useFactory: async (authService: AuthService) => ({
context: ({ req, res, payload, connection }: GqlContext) => ({ req, res, payload, connection }),
subscriptions: {
onConnect: (connectionParams: ConnectionParams) => {
const connectionParamsLowerKeys = mapKeysToLowerCase(connectionParams);
const authToken: string = ('authorization' in connectionParamsLowerKeys)
&& connectionParamsLowerKeys.authorization.split(' ')[1];
if (authToken) {
const jwtPayload: GqlContextPayload = authService.getJwtPayLoad(authToken);
return { currentUser: jwtPayload.username, jwtPayload, headers: connectionParamsLowerKeys };
}
throw new AuthenticationError('authToken must be provided');
},
},
}),
inject: [AuthService],
}),
note for GraphQLModule.forRootAsync, imports: [AuthModule], useFactory: async (authService: AuthService) and inject: [AuthService]
thanks m8s, and to @bcba25 to, great question ;)
it guide me to the solution :)
thanks to all
sorry I not that above link is broken, has an extra 'l' ..394l in the end,
this is the correct link Document how authentication guards for GraphQL Subscriptions work
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
What you can do to protect your GraphQL subscription endpoint is this: