带有 Passport JWT 的 Apollo 服务器

Apollo Server with Passport JWT

我正在尝试使用 passport JWT 实现 graphql,但行为不是我所期望的。

graphql 端点不应该通过身份验证关闭,因为一些查询是 public,我想知道如果用户使用解析器登录,我该如何打开 graphql 并在内部进行过滤?

这是我现在的代码,它可以与 JWT 一起正常工作,但它会关闭 graphql 端点并返回 "Unauthorized",除非我指定令牌。

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

import passport from 'passport'
import passportJWT from 'passport-jwt'

import schema from './schemas'

const { JWT_SECRET } = process.env

const path = '/graphql'

// ...

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

// ...

const { Strategy, ExtractJwt } = passportJWT

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

// ...

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

  if (user) {
    return done(null, {
      id: user.id
    })
  }

  return done(new Error('The user has not been found'), null)
})

passport.use(strategy)

// ...

const app = express()

passport.initialize()

app.use(path, passport.authenticate('jwt', { session: false }))

// ...

const server = new ApolloServer({
  schema
})

server.applyMiddleware({
  app,
  path
})

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

如果 JWTToken 不存在,passport-jwt 将失败,未授权状态传递给信息。你可以像下面这样处理它们

app.use(path, bodyParser.json(), function(req, res, next) {
    passport.authenticate('jwt', (err, user, info) => {
        if (err) { res.status(500).send({"error": err}); return; }
        next();
    })(req, res, next);
});