DEV Community

hasusozam
hasusozam

Posted on

Passport JWT with GraphQL (Apollo Server 2)

I was studying and reading about authentication in GraphQL and people told me (devs from Docker and Facebook) that GraphQL doesn't need to know anything about authentication, in fact your schemas and resolvers should be simple and thin, the authentication must be done outside GraphQL, and for that I did this simple Passport JWT authentication in GraphQL to show what I understood about that.

import express from 'express'
import { ApolloServer } from 'apollo-server-express'

// ...
import passport from 'passport'
import passportJWT from 'passport-jwt'
import jwt from 'jsonwebtoken'
// ...

import schema from './schemas'

const { GRAPHQL_PORT, JWT_SECRET } = process.env

// ...
const users = [
  {
    id: 1,
    name: 'John',
    email: 'john@mail.com',
    password: 'john123'
  }
]

// generate a jwt token for testing purposes
console.log(jwt.sign(users[0], JWT_SECRET))

// ...

const { Strategy, ExtractJwt } = passportJWT

const params = {
  secretOrKey: JWT_SECRET,
  jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken()
}

const strategy = new Strategy(params, (payload, done) => {
  const user = users.find(user => user.id === payload.id) || null

  return done(null, user)
})

passport.use(strategy)

// ...

const app = express()

// ...

passport.initialize()

app.use('/graphql', (req, res, next) => {
  passport.authenticate('jwt', { session: false }, (err, user, info) => {
    if (user) {
      req.user = user
    }

    next()
  })(req, res, next)
})

// ...

const server = new ApolloServer({
  schema,
  context: ({ req }) => ({
    user: req.user
  })
})

server.applyMiddleware({
  app
})

app.listen(
  {
    port: GRAPHQL_PORT
  },
  () => console.log(`The GraphQL server is running on port ${GRAPHQL_PORT}`)
)
Enter fullscreen mode Exit fullscreen mode

Now the resolvers will have the user authenticated, but the resolvers are not responsible to make auth verification, so instead it's probably better to make a schema directive to check for authentication or even passing the current user to some kind of service in the backend to check instead of if (user) {... in the resolvers.

What are your thoughts about the code, any room for improvement?

Top comments (3)

Collapse
 
guillaumepn profile image
guillaumepn

Hi, I'm still a beginner with the Graphql/Apollo stack, and I'm trying to get a good and secure auth system, I thought about Passport and discovered your post

After 2 months, are you still using it, is it efficient ? Or did you learn other ways of doing this, or best practices you didn't know then ? I'm using apollo-server-express as well

Thank you for the interesting post btw

Collapse
 
netlander profile image
Yaseen

@guillaumepn did you make any progress in figuring out best practices and a decent architecture for GraphQL authentication?

PS: Interesting how the last sentence in the port asks readers of their thoughts then the author doesn't bother replying.

Collapse
 
ezalivadnyi profile image
Eugene Zalivadnyi

Thanks for this article. Could you explain how to make "a schema directive to check for authentication or even passing the current user to some kind of service in the backend to check"?