简体   繁体   English

GraphQL 服务器上下文中的 Passport Azure AD 身份验证

[英]Passport Azure AD authentication in GraphQL Server Context

hoping someone can help a noob with some async javascript issues.希望有人可以帮助菜鸟解决一些异步 javascript 问题。

I am attempting to secure a GraphQL server instance using Passport and the passport-azure-ad strategy.我正在尝试使用 Passport 和 Passport-azure-ad 策略来保护 GraphQL 服务器实例。 I can see from logs that the incoming Access Token is validated correctly and all of the passport code is working as expected.我可以从日志中看到传入的访问令牌已正确验证并且所有护照代码都按预期工作。

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;
  },
});

The authErr and authUser params are correctly being passed to the custom callback, however the context is returned before the callback is executed. authErr 和 authUser 参数被正确传递给自定义回调,但是在执行回调之前返回上下文。

Ideally I would like to if (!user) throw new AuthenticationError('you must be logged in');理想情况下,我想if (!user) throw new AuthenticationError('you must be logged in'); in the context block if the user is not available, however due to the asynchronous nature of the code I don't have access to it.如果用户不可用,则在上下文块中,但是由于代码的异步性质,我无权访问它。

How can I make the code in the context wait until the custom passport.authenticate callback has executed?如何让上下文中的代码等待自定义passport.authenticate回调执行? Or alternatively is there a better way for me to do this?或者有没有更好的方法让我做到这一点? I am new to apollo server, passport and even working with node, so I wouldn't be surprised if I was doing something wrong.我是阿波罗服务器、护照甚至使用节点的新手,所以如果我做错了什么,我不会感到惊讶。

Right now it seems that my setting of context.user isn't even available in the context delivered to the resolvers.现在似乎我的context.user设置在传递给解析器的上下文中甚至不可用。

Thanks in advance.提前致谢。

Basically, you need to "promisify" you authenticate request:基本上,您需要“承诺”您的身份验证请求:

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);
});

and then use it in the context like this:然后在这样的上下文中使用它:

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM