0

希望有人可以帮助菜鸟解决一些异步 javascript 问题。

我正在尝试使用 Passport 和 passport-azure-ad 策略来保护 GraphQL 服务器实例。我可以从日志中看到传入的访问令牌已正确验证,并且所有护照代码都按预期工作。

const passport = require('passport');
const OIDCBearerStrategy = require('passport-azure-ad').BearerStrategy;

...

// Setting up the Strategy and verify function
const bearerStrategy = new OIDCBearerStrategy(options, (token, done) => {
  if (!token.scp.includes('check-this-scope')) {
    return done(null, false, { message: 'User not authorized to access resource' });
  }
  return done(null, token);
});

passport.use('oauth-bearer', bearerStrategy);

...

const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: async (context) => {
    passport.authenticate('oauth-bearer', (authErr, authUser, authInfo) => {
      if (!authUser) context.authErr = authErr || authInfo;
      else context.user = authUser;
    })(context.req, context.res);
    return context;
  },
});

authErr 和 authUser 参数正确地传递给自定义回调,但是在执行回调之前返回上下文。

理想情况下,如果用户不可用,我想if (!user) throw new AuthenticationError('you must be logged in');在上下文块中,但是由于代码的异步性质,我无权访问它。

如何使上下文中的代码等到执行自定义 passport.authenticate 回调?或者,我是否有更好的方法来做到这一点?我是阿波罗服务器、护照甚至使用节点的新手,所以如果我做错了什么我不会感到惊讶。

现在看来,我的设置context.user甚至在传递给解析器的上下文中都不可用。

提前致谢。

4

1 回答 1

1

基本上,您需要“承诺”您验证请求:

const authOauthBearer = ({ req, res }) => new Promise((resolve, reject) => {
  passport.authenticate('oauth-bearer', (authErr, authUser, authInfo) => {
    if (!authUser) reject(authErr || authInfo);
    else resolve(authUser);
  })(req, res);
});

然后在这样的上下文中使用它:

context: async (context) => {
  try {
    const { user } = authOauthBearer(context);
    context.user = user;
  } catch(error) {
    // you may want to escalate the auth issue to the client so you can just throw:
    // throw error;

    // or you can store the auth error in the context
    context.authError = error;
  }
  return context;
}
于 2020-11-24T12:37:58.297 回答