我目前在域(例如 http://backend.com)上托管了 loopbackJS api,并通过 Auth0 设置了第三方身份验证。我有一个作为 SPA 在另一个域上托管的前端(例如 http://frontend.com)
loopback-component-passport 似乎在前端与 API 位于同一域时工作正常,它相应地设置 userId
和 access_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.com 或 http://frontend.com ,以指定者为准)。 returnTo
查询参数似乎也按预期工作。
有没有办法在重定向回前端之前捕获access_token
,并以某种方式传达它(例如查询参数,除非那样太不安全)。
最佳答案
经过更多调查,我决定使用此方法将访问 token 和 userId 从 loopbackjs 后端传递到单独的前端。这是 documented在 github pull-request 上,使用 passport-configurator 的 customCallback。
其他引用此内容的地方是 this fork , issue #102 , issue #14和 pull 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/