question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Authentication with GraphQL using @Guard

See original GitHub issue

I’m submitting a…


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.

Current behavior

The /graphqlroute is accessible.

Expected behavior

The /graphql should be not accessible.

Minimal reproduction of the problem with instructions

@Module({
  imports: [GraphQLModule, AuthModule],
  controllers: [AppController]
})
export class ApplicationModule implements NestModule {
  constructor(private readonly graphQLFactory: GraphQLFactory) {}

  configure(consumer: MiddlewaresConsumer) {
    const typeDefs = this.graphQLFactory.mergeTypesByPaths('./**/*.graphql');
    const schema = this.graphQLFactory.createSchema({ typeDefs });

    consumer
      .apply(graphiqlExpress({ endpointURL: '/graphql' }))
      .forRoutes({ path: '/graphiql', method: RequestMethod.GET })
      .apply(graphqlExpress(req => ({ schema, rootValue: req })))
      .forRoutes({ path: '/graphql', method: RequestMethod.ALL });
  }
}
@Module({
  components: [AuthService, JwtStrategy],
  controllers: [AuthController],
})
export class AuthModule implements NestModule {
  public configure(consumer: MiddlewaresConsumer) {
    consumer
      .apply(passport.authenticate('jwt', { session: false }))
      .forRoutes({ path: '/graphql', method: RequestMethod.ALL });
  }
}

What is the motivation / use case for changing the behavior?

Environment


Nest version: 4.5.10

 
For Tooling issues:
- Node version: 9.4.0  
- Platform:  Mac

Others:

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:1
  • Comments:24 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
mchmielarskicommented, Feb 9, 2018

For me current implementation of nestjs/graphql has two problems.

  1. it use apollo-server-express directly, so response is send directly from this middleware and connection is closed - it breaks nest flow.

  2. guards use rootValue as dataOrRequest for canActivate, it’s hard to use if we would like to use guards on deeper level than root - I think that it should to use context from GraphQL

here is very simple example with some changes which try to resolve above problems: https://github.com/mchmielarski/nest-graphql-example

1reaction
jrosseelcommented, Feb 20, 2018

@mchmielarski Thanks for linking these issues!

I did it somewhat different but experience the same problem. Applying app.useGlobalGuards(aGuard) will not trigger that guard for calls to a graphql endpoint.

How I did authentication/authorisation: Instead of crearing a JwtStrategy object and putting it before the routes, inside a global guard called ClaimsGuard I capture all requests. In the guard, if controller endpoints or resolvers are annotated with @Unauthorised() I allow everything. If they are not, I look for a jwt token, verify it myself with the secret in my database and extract its payload. Its payload is an object of type BearerToken that contains claims.

I then match the claims that user has with the claims combined of controller/resolver level and controller/resolver endpoint.

src: https://github.com/elewa-company/elewa-lms/blob/master/elewa-backend/src/modules/auth/gaurds/claims.gaurd.ts

I set the strategy on where to get the token by simple inheritance

@Guard()
export class HttpClaimsGuard extends ClaimsGuard {

  constructor(authConfigService : AuthConfigService, reflector: Reflector) {
    super(authConfigService, 
              reflector, 
              ExtractJwt.fromAuthHeaderAsBearerToken())
  }

}

On server start, I then register the guard.

const authGuard = app.select(AuthModule)
                                      .get(HttpClaimsGuard);
 
 app.useGlobalGuards(authGuard);

This strategy works for controller endpoints and the first line (console.log) of the guard is called at each controller endpoint. (I still need to test all use cases so might still contain some bugs)

My issue, and what I think is a bug, is that that console.log is not called when accessing graphql endpoints. So the guard is for some reason ignored.

More info in #434

P.S. My Graphql Endpoint configuration:

configure(consumer: MiddlewaresConsumer) {
    const typeDefs = this.graphQLFactory.mergeTypesByPaths('./**/*.gql');
    const schema = this.graphQLFactory.createSchema({ typeDefs });

     // Dev Graphiql endpoint
     if(!production)
      consumer
        .apply(graphiqlExpress({ endpointURL: '/graphql' }))
        .forRoutes({ path: '/graphiql', method: RequestMethod.GET })

    consumer
      .apply(graphqlExpress(req => ({ schema, rootValue: req, context: req })))
        .forRoutes({ path: '/graphql', method: RequestMethod.ALL });
  }
Read more comments on GitHub >

github_iconTop Results From Across the Web

Authentication and authorization - Apollo GraphQL Docs
Control access to your GraphQL API. ... Authentication is determining whether a given user is logged in, and subsequently determining which user someone...
Read more >
how to implement user guards in nestjs graphql - Stack Overflow
This is what I'm using for GraphqlJwtAuthGuard based on documentaion: @Injectable() export class GqlJwtAuthGuard extends AuthGuard('jwt') ...
Read more >
Authentication and Authorization in GraphQL – The Guild
To add guards to your resolvers, you can use a simple Middleware approach, and wrap your resolver with a function that checks if...
Read more >
Authentication - Lighthouse PHP
You can configure a default guard to use for authenticating GraphQL requests in lighthouse.php . 'guard' => 'api',. This setting is used whenever...
Read more >
GraphQL Authentication and Authorization in Node.js
In today's article we are going to work with the user's permissions, first we will create the account, then we will go to...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found