express - Auth0 LoopbackJS API access token using 3rd party login -
i have loopbackjs api hosted on domain (e.g. http://backend.com), third party authentication setup via auth0. have front-end hosted spa on domain (e.g. http://frontend.com)
loopback-component-passport seems work fine when front-end on same domain api, , sets userid
, access_token
cookies accordingly. however, front-end in production on different domain api, example api auth link like:
"http://backend.com/auth/auth0?returnto=" + encodeuricomponent("http://frontend.com")
the backend has used same auth pattern in loopback-passport-example, providers.json
file specifies connection details auth0 (although have tried other social providers such 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 }
the front-end (http://frontend.com) has link on page redirect api authentication:
<a href="http://backend.com/auth/auth0">login</a>
clicking on link redirects auth0 properly, , can login. redirects specified target (http://backend.com or http://frontend.com, whichever specified). returnto
query parameter seems work expected.
is there way capture access_token
before redirecting front-end, , somehow communicate (e.g. query parameters, unless insecure).
after more investigation, settled on method use passing access token , userid loopbackjs backend, separate front-end. documented on github pull-request, using customcallback of passport-configurator.
other places have referenced this fork, issue #102, issue #14 , pull request #155.
there 2 options here, either use fork of loopback-component-passport (e.g. 1 referenced above) npm dependency, or provide customcallback passport configuration option documented.
i wanted little more control on format of url, ended customcallback method. in loopback-example-passport, inside /server/server.js
there basic code passing providers.json
passport configurator:
var config = {}; try { config = require('../providers.json'); } catch (err) { console.trace(err); process.exit(1); // fatal } passportconfigurator.init(); (var s in config) { var c = config[s]; c.session = c.session !== false; passportconfigurator.configureprovider(s, c); }
this can replaced documented customcallback code, passport
variable being assigned 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); });
in above example, have copied successredirect
function used in passport-configurator.js
, use same returnto
query parameter. option within providers.json
can set e.g. "redirectwithtoken": true
, results in redirect auth strategies need external redirect.
one more final bit of code in case returnto
redirect required. if exists query parameter, should added @ session level:
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(); });
now, if backend api @ url such http://api.com
, , front-end hosted @ domain e.g. http://gui.com
, authentication link can placed on front-end:
<a href="http://api.com/auth/facebook?returnto=http%3a%2f%2fgui.com">login!</a>
this result in api auth call, redirect returnto
link access token , userid in query parameters.
potentially in future, 1 of issues or other pull requests merged provide more ideal method 3rd party domain redirection, until method work well.
Comments
Post a Comment