Using !user.email_verified

hi

I’ve managed to implement login, and i’ve come to add rules in order to whitelist specific email addresses, but i noticed that the whitelist is ignored on signup. So i wanted to only accept verified users through, but however i implement that rule seems to cause my app to give a ERR_TOO_MANY_REDIRECTS from either / both my domain, but also my auth0 domain.

I’ve tried creating it as two rules, with the whitelist rule first or the verified email first,
i’ve tried combining it into one rule

function (user, context, callback) {
 
  const whitelist = [ 'bigcoops@gmail.com', 'stockport.badders.results@gmail.com' ]; //authorized users
  const userHasAccess = whitelist.some(
    function (email) {
      return email === user.email;
    });

  if (!user.email_verified || !userHasAccess) {
    return callback(new UnauthorizedError('Access denied.'));
  }

  callback(null, user, context);
}

or:

function (user, context, callback) {

  // Access should only be granted to verified users.
  if (!user.email || !user.email_verified) {
    return callback(new UnauthorizedError('Please verify your email before logging in.'));
  }

  const whitelist = [ 'bigcoops@gmail.com', 'stockport.badders.results@gmail.com' ]; //authorized users
  const userHasAccess = whitelist.some(
    function (email) {
      return email === user.email;
    });

  if (!userHasAccess) {
    return callback(new UnauthorizedError('Access denied.'));
  }

  callback(null, user, context);
}

but none of these have worked, and all result in the same symptom. removing the !user_email_verified part resolves the problem, but leaves me with the signup problem.

any suggestions?

Hey there @stockport.badders, I’m still looking into what may be going on here but it may have something to do with the callbacks on your tenant between http and https, which could be causing the ERR_TOO_MANY_REDIRECTS. Also If you could please snag us a HAR file capturing your workflow when reproducing the error and DM it over, it may be able to help us look at what’s going on at a deeper level. Thanks in advance!

https://auth0.com/docs/application-auth/current/server-side-web

thanks james i’ve attached the HAR

hope that helps :slight_smile:

Hi again @James.Morrison , i’ve spent a fair amount of time over the weekend making sure any http traffic is redirected to https in the hope that it would help. but apparently not.

let me know if you need me to do anymore - the problem still persists. :frowning:

Thank you for sharing the HAR file, I’ll give it a look and see what may be going on.

any luck yet @James.Morrison ?

In the HAR file capture we see there is a 404 when reaching out to /user/sso but this expected as discussed deeply here in this thread. However there doesn’t seem to be anything additional of note from the capture relating to your issue. I am still investigating what may be occurring and will share what I find :+1:

I wanted to follow up with you @stockport.badders, after further investigation with our Support team it appears there is a problem with the logic handling the callback inside your application. It seems like your callback endpoint is redirecting to your login endpoint instead of your application page, then your login endpoint redirecting back to Auth0. This seamlessly authenticates you which is why you won’t see a login prompt but it will redirect back to your callback endpoint. Which restarts the entire loop again thus producing the ERR_TOO_MANY_REDIRECTS error.

When you get a minute can you take a look at that and see if there is anything you can adjust. Thanks!

Thanks James,

i think i understand…
but, i’m not entirely sure what to change:

app.get('/login', passport.authenticate('auth0', {
      scope: 'openid email profile',
      rememberLastLogin: false
    }), function (req, res) {
      res.redirect('/');
    });

    // Perform the final stage of authentication and redirect to previously requested URL or '/user'
    app.get('/callback', function (req, res, next) {
      passport.authenticate('auth0', function (err, user, info) {
        if (err) { return next(err); }
        if (!user) { return res.redirect('/login'); }
        req.logIn(user, function (err) {
          if (err) { return next(err); }
          const returnTo = req.session.returnTo;
          delete req.session.returnTo;
          res.redirect(returnTo || '/user');
        });
      })(req, res, next);
    });

    // Perform session logout and redirect to homepage
    app.get('/logout', (req, res) => {
      req.logout();
      res.redirect('/');
    });

    app.get('/user', secured(), function (req, res, next) {
      const { _raw, _json, userProfile } = req.user;
      res.render('beta/user', {
        userProfile: JSON.stringify(userProfile, null, 2),
        static_path:'/static',
        theme:process.env.THEME || 'flatly',
        pageTitle : "User Profile",
        pageDescription : "User Profile",
      });
    });


    app.get('/scorecard-beta',function(req,res){
      res.render('index-scorecard',{
        static_path:'/static',
        theme:process.env.THEME || 'flatly',
        pageTitle : "Scorecard",
        pageDescription : "Enter some results!",
        result:[
          {
            id:7,
            name:"Premier"
          },
          {
            id:8,
            name:"Division 1"
          },
          {
            id:9,
            name:"Division 2"
          },
          {
            id:10,
            name:"Division 3"
          },
          {
            id:11,
            name:"Division 4"
          }
        ]
      })
    })

are the 4 involved pages. i can see where it redirects to /login, but surely that’s the correct behaviour if !user

module.exports = function() {
  return function secured (req, res, next) {
    // console.log(req);
    if (req.user) { return next(); }
    req.session.returnTo = req.originalUrl;
    res.redirect('/login');
  };
};

but i think this looks okay too since it checks if the user exists and then goes back to the route, if your not logged in it captures the Url and sends you to login. :confused:

Support recommends that one thing you might try is changing if (!user) { return res.redirect('/login'); } in your callback function. If there’s no user, it means some error might have occurred, so this would grant you the opportunity to show the error instead of redirecting to the login again. Please let us know if this helps you in your quest @stockport.badders, thanks!

hmmmm.
i replaced it with:

if (!user) {
             res.render('beta/failed-login', {
                static_path:'/static',
                theme:process.env.THEME || 'flatly',
                pageTitle : "Access Denied",
                pageDescription : "Access Denied",
              });
              // return res.redirect('/login');
            }

which unfortunately created a new problem, i can’t get back to the login page. i’ve cleared all the cookies i can see, but regardless of how i logout, everytime i try to access the /user page i just get the ‘Access Denied’ page that i’ve created.
the url looks like:

http://127.0.0.1:3000/callback?error=unauthorized&error_description=Access%20denied.&state=f6MVnCXGoTdVKQIDB5aKGyZd

it’s okay - i sorted it by updating my logout route to the following:

    app.get('/logout', (req, res) => {
      req.logout();
      res.redirect('https://'+ process.env.AUTH0_DOMAIN + '/v2/logout?clientid='+ process.env.AUTH0_CLIENTID +'returnTo=https://stockport-badminton.co.uk');
    });

Seems to work a treat now :slight_smile:

1 Like

Awesome @stockport.badders, I’m glad you were able to solve it and thank you for sharing the solution!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.