Auth0 Home Blog Docs

How to autoforward from a login server to correct site and prevent unauthorized client from snooping on a site that they don't belong to

callback-urls
express

#1

Hi everyone,
I am trying to set up the following: An express server serves as the sign on for the user. Once they sign on, we redirect them to a particular subdomain based on a value in their profile.app_metadata.company. So if they work for company1 we direct them to company1.oursite.com.

At the same time someone with company2 would be redirected to login.oursite.com if they weren’t logged in and redirected to their site even if they directly typed in company1.oursite.com if they were part of company 2.

I’m trying to figure out how to best set this up, I can see that I have access to my profile in the callback of Auth0Strategy, but the callbackURL is set in the input parameters while I don’t have access to my profile until the callback. How can I perform this autoforwarding from my login.oursite.com to the correct webserver and autoforwarding from a webserver back to the login.oursite.com server if the user tries to access a site other than their own?

I’m pretty sure that I need to modify this, but I am not quite sure how:

var strategy = new Auth0Strategy({
    domain:       process.env.AUTH0_DOMAIN,
    clientID:     process.env.AUTH0_CLIENT_ID,
    clientSecret: process.env.AUTH0_CLIENT_SECRET,
    callbackURL:  process.env.AUTH0_CALLBACK_URL || 'http://localhost:3000/callback'   }, function(accessToken, refreshToken, extraParams, profile, done) {
    console.log('callbacked!', profile.app_metadata.company)

    // accessToken is the token to call Auth0 API (not needed in the most cases)
    // extraParams.id_token has the JSON Web Token
    // profile has all the information from the user
    return done(null, profile);   });

Thanks!


#2

I would consider the following approach:

  1. You configure your passport strategy in the way you included in your question; you only use the callback in the strategy itself if you want to enrich/translate the user profile.
  2. You implement a login.oursite.com route that is protected with the above strategy; this route will be the redirect/callback URL for your client application.
  3. You use a session storage that is accessible both to login.oursite.com and companyX.oursite.com express servers.
  4. You configure the session for all express servers to use the shared session storage.
  5. You configure the login.oursite.com express session to write the session cookie at the .oursite.com parent domain so that the cookie is also available to sub-domains.
  6. You ensure that passport uses sessions.

The login.oursite.com route will be something like:

router.get('/', function (req, res, next) {
  passport.authenticate('auth0', function (err, user, info) {
    if (err) { return next(err); }

    if (!user) { return res.redirect('/'); }

    // We got a user authenticated with success; so persist a session
    req.logIn(user, function (err) {
      if (err) { return next(err); }

      // Redirect the user to the sub-domain they belong
      return res.redirect(`https://${user.company}.oursite.com`);
    });
  })(req, res, next);
});

The routes for companyX.oursite.com will be something like:

router.get('/index', function (req, res, next) {
  if (!req.user) {
    // No user authenticated; redirect to login
    return res.redirect("https://login.oursite.com");
  }

  if (req.user.company !== "[CompanyX]") {
    // User is from a different company than the one
    // associated with the current site
    return res.redirect(`https://${user.company}.oursite.com`);
  }

  // provide response
});

The previous logic could be extracted to a common middleware and easily run for all routes.

This assumes that you use a cookie based session to keep the notion of authenticated user available to all domains and that even though there are different sub-domains being used the underlying application is the same and as such shares a common passport configuration that allows the authenticated user to be automatically detected.


#3