express - 使用第 3 方登录的 Auth0 LoopbackJS API 访问 token

标签 express passport.js loopbackjs

我目前在域(例如 http://backend.com)上托管了 loopbackJS api,并通过 Auth0 设置了第三方身份验证。我有一个作为 SPA 在另一个域上托管的前端(例如 http://frontend.com)

loopback-component-passport 似乎在前端与 API 位于同一域时工作正常,它相应地设置 userIdaccess_token cookie。但是,我的生产前端与 API 位于不同的域中,例如 API 身份验证链接类似于:

"http://backend.com/auth/auth0?returnTo="+ encodeURIComponent("http://frontend.com")

后端使用了与 loopback-passport-example 中相同的身份验证模式,其中 providers.json 文件指定了 Auth0 的连接详细信息(尽管我也尝试过其他社交提供商,例如 Facebook)。

  "auth0-login": {
    "provider": "auth0",
    "module": "passport-auth0",
    "clientID": "AUTH0_CLIENT_ID",
    "clientSecret": "AUTH0_CLIENT_SECRET",
    "callbackURL": "/auth/auth0/callback",
    "authPath": "/auth/auth0",
    "callbackPath": "/auth/auth0/callback",
    "successRedirect": "/",
    "failureRedirect": "/login",
    "scope": ["email"],
    "failureFlash": true
  }

前端(http://frontend.com)在页面上有一个重定向到 API 认证的链接:

<a href="http://backend.com/auth/auth0">Login</a>

单击此链接会正确重定向到 Auth0,我可以登录。然后它重定向到指定的目标( http://backend.comhttp://frontend.com ,以指定者为准)。 returnTo 查询参数似乎也按预期工作。

有没有办法在重定向回前端之前捕获access_token,并以某种方式传达它(例如查询参数,除非那样太不安全)。

最佳答案

经过更多调查,我决定使用此方法将访问 token 和 userId 从 loopbackjs 后端传递到单独的前端。这是 documented在 github pull-request 上,使用 passport-configurator 的 customCallback。

其他引用此内容的地方是 this fork , issue #102 , issue #14pull request #155 .

这里有 2 个选项,要么使用 loopback-component-passport 的分支(例如上面的 referenced)作为您的 npm 依赖项,要么提供 customCallback 作为通行证配置选项 documented .

我想对 URL 的格式有更多的控制,所以最终使用了 customCallback 方法。在 loopback-example-passport ,在 /server/server.js 中有一些基本代码用于将 providers.json 传递给 Passport 配置器:

var config = {};
try {
  config = require('../providers.json');
} catch (err) {
  console.trace(err);
  process.exit(1); // fatal
}
passportConfigurator.init();
for (var s in config) {
  var c = config[s];
  c.session = c.session !== false;
  passportConfigurator.configureProvider(s, c);
}

这基本上可以用记录的 customCallback 代码替换,passport 变量由 passportConfigurator.init() 分配:

var providers = {};
try {
  providers = require('../providers.json');
} catch (err) {
  console.trace(err);
  process.exit(1); // fatal
}

const passport = passportConfigurator.init();
Object.keys(providers).forEach(function(strategy) {

  var options = providers[strategy];
  options.session = options.session !== false;

  var successRedirect = function(req) {
    if (!!req && req.session && req.session.returnTo) {
      var returnTo = req.session.returnTo;
      delete req.session.returnTo;
      return returnTo;
    }
    return options.successRedirect || '';
  };

  options.customCallback = !options.redirectWithToken 
    ? null 
    : function (req, res, next) {
      var url = require('url');
      passport.authenticate(
        strategy,
        {session: false},
        function(err, user, info) {
          if (err) {
            return next(err);
          }

          if (!user) {
            return res.redirect(options.failureRedirect);
          }
          var redirect = url.parse(successRedirect(req), true);

          delete redirect.search;

          redirect.query = {
            'access_token': info.accessToken.id,
            'userId': user.id.toString()
          };
          redirect = url.format(redirect);
          return res.redirect(redirect);
        }
      )(req, res, next);
  };

  passportConfigurator.configureProvider(strategy, options);
});

在上面的示例中,我基本上复制了 passport-configurator.js 中使用的 successRedirect 函数,以使用相同的 returnTo 查询范围。可以设置 providers.json 中的一个选项,例如"redirectWithToken": true,这导致仅对需要外部重定向的身份验证策略进行重定向。

还有最后一点代码,以防需要 returnTo 重定向。如果它作为查询参数存在,则应在 session 级别添加:

app.use(function(req, res, next) {
  var returnTo = req.query.returnTo;
  if (returnTo) {
    req.session = req.session || {};
    req.session.returnTo = require('querystring').unescape(returnTo);
  }
  next();
});

现在,如果后端 api 位于诸如 http://api.com 之类的 URL,而前端托管在另一个域,例如http://gui.com,可以在前端放一个认证链接:

<a href="http://api.com/auth/facebook?returnTo=http%3A%2F%2Fgui.com">Login!</a>

这将导致 API 身份验证调用,然后使用查询参数中的访问 token 和 userId 重定向回 returnTo 链接。

可能在未来,其中一个问题或其他拉取请求将被合并,这可以为第 3 方域重定向提供更理想的方法,但在此之前这种方法运行良好。

关于express - 使用第 3 方登录的 Auth0 LoopbackJS API 访问 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37430452/

相关文章:

node.js - 通过套接字的身份验证方法

mysql - 为什么我的 Passport 应用程序不能对用户进行身份验证?

javascript - 我可以使用 Passportjs 仅对某些 google 用户进行身份验证吗?

node.js - lb-ng 环回命令从异步模块返回 "Cannot read property ' apply' of undefined"

node.js - 在 Passport.js 和 Express 路由器中使用 next

javascript - 从路由器内关闭服务器

node.js - winston 未知记录器级别 : undefined

javascript - node/express - 如何将用户输入呈现到页面?

Restful 最佳实践。这是否违反了无状态约束?

javascript - 在环回中过滤远程方法