Verification Email question

Is it possible to only send the verification email if the user clicks the opt-in checkbox on the widget during sign up? If checked it adds a flag to the users metadata called newsletter and sets it to true.

Hi @molly.kelsey,

Welcome to the Community.

Yeah its absolutely possible. You need to customize the login page screen in universal login setting menu. Here you can set any flag in user_metadata of user profile at auth0.

Thanks @rashid779939. I already have this set up as part of my login (see code below). I’d like to trigger the welcome email only when that checkbox is checked.

additionalSignUpFields: [{
        type: "checkbox",
        name: "newsletter",
        prefill: "false",
        placeholder: "Keep me updated"
      }],

You need to set email verified flag false if you want to send verification email and set it true if you don’t want to send verification email. For more detail refer to below post:

Email verification for some but not all applications

Hope answer the question, please provide feedback accordingly.

@rashid779939 I’ve added the following hook. When testing I keep getting a 429 error, too many api requests.

module.exports = function (user, context, cb) {
  var response = {};

  response.user = user;
	
  if (user.user_metadata.newsletter === 'true')
  {
    user.email_verified = false;
    context.updateUser({id: user.user_id}, {email_verified: false});
  }
  else
  {
    user.email_verified = true;
    context.updateUser({id: user.user_id}, {email_verified: true});
  }
  
  cb(null, response);
};

Too many API requests error comes when you hit any management API multiple times with out waiting response. I am not getting why you seeing this error in hook. Are you pre-reg hook or post-reg hook?
If you explain your whole flow that would help to narrow down the ambiguity.

1 Like

@rashid779939 It’s a pre registration hook. I’ve tried that and a rule and i’m still not able to set the email_verified flag to true.

This is the rule I was trying but it was throwing an unauthorized error and didn’t log me in after sign up.

function (user, context, callback) {
  var ManagementClient = require('auth0@2.9.1').ManagementClient;
  var management = new ManagementClient({
     token: auth0.accessToken,
     domain: auth0.domain
  });
  var response = {};

  response.user = user;
	
  if (user.user_metadata.newsletter === 'true')
  {
    user.email_verified = false;
    response.user.email_verified = false;
    management.updateUser({id: user.user_id}, {email_verified: false});
  }
  else
  {
    response.user.email_verified = true;
    user.email_verified = true;
    management.updateUser({id: user.user_id}, {email_verified: true});
  }
}

Also, we are using the log/in sign up widget.

I’ve tried that and a rule and i’m still not able to set the email_verified flag to true.

As for the email_verified flag, it’s a ‘protected’ attribute in regards to direct assignments, see this thread and my comments in there.

Basically, you cannot assign a value directly like this: user.email_verified = true; (or let’s say, just like this it doesn’t have any effect on the email_verified claim in the ID token).

As you can see in the example above, I also update the user via management API (like you do) as well and also add it in the ID token.

If your above code is the complete Rule, then the callback is missing; compare with the example in the linked post.

1 Like

I tried out the following code with no luck. My flag will not change to true.

function (user, context, callback) {

  if (user.user_metadata.newsletter === true)  {
	
var ManagementClient = require('auth0@2.6.0').ManagementClient;
var management = new ManagementClient({
    token: auth0.accessToken,
    domain: auth0.domain
});
console.log('Client:', management, 'Newsletter:', user.user_metadata.newsletter);
 // persist in user store
management.updateUser({id: user.user_id}, {email_verified:true})
.then(function(u){    
  context.idToken.email_verified = u.email_verified;
  context.idToken.email = u.email;    
  callback(null, u, context);
})
.catch(function(err){
  callback(err);
});     
  } else { 
    callback(null, user, context);
  }
}

Did you debug with console.log and Realtime Webtask logs that you actually get to that point of the successful callback?

console.log(JSON.stringify(u)); and also console.log(JSON.stringify(context.idToken)); (right before the callback) at that point?

Because the code looks good so far.

@mathiasconradt,
I try this on my tenant and monitor using run-time logs extension. Email_verified get update in user profile in hook scope but not reflect in user profile create at auth0. I think it needs to discuss with developer internally, seems a bug.

I added the logs, but they did not show up in the auth0 debugger.

I switched the auth0 library to 2.9.1. With 2.6.0 i was getting an error when trying to log in post registration. Switching libraries resolved that.

Also, I tried adding the console.log() statement at the beginning of my if statement and it didn’t log. Maybe an issue there?

EDIT: had to change my if statement to this user.user_metadata.newsletter !== 'true'
It’s updating the user object now, but even when the flag is set to false, the verification email still sends.

Is this now in a Rule or Hook?

A rule. Should it be in a hook?

A Rule is triggered upon successful authentication. The Hook is triggered upon signup.
If you put the logic in the Rule, at that point, the email verification mail is already sent, because that happens at signup. So, when a user signs up, it’s basically like this:

Signup --> [Hook] --> Verification Mail Sent (if needed) --> [Rule Engine] --> Return via Callback to App with Tokens

Therefore, it needs to be in the Pre-User-Reg Hook.

1 Like

I’ve changed it to a hook and am getting the following error when attempting to sign up,
“WE’RE SORRY, SOMETHING WENT WRONG WHEN ATTEMPTING TO SIGN UP.”

module.exports = function (user, context, callback) {
  
  if (user.user_metadata.newsletter !== 'true')  {
		//auth02.9.1
    var ManagementClient = require('auth0@2.6.0').ManagementClient;
    var management = new ManagementClient({
        token: auth0.accessToken,
        domain: auth0.domain
    });

 // persist in user store
management.updateUser({id: user.user_id}, {email_verified:true})
.then(function(u){    
  context.idToken.email_verified = u.email_verified;
  context.idToken.email = u.email;  
  console.log(JSON.stringify(u));
  console.log(JSON.stringify(context.idToken));
  callback(null, u, context);
})
.catch(function(err){
  callback(err);
});     
  } else { 
    callback(null, user, context);
  }
}

Anything in the logs? Best to log the error to console, if it doesn’t show in the logs already.
Haven’t tested it myself but I believe it’s the pre-user reg hook, the user doesn’t yes exist (not yet persisted in the user store); probably the reason that updateUser fails.

"code": 500, 
"error": "Script generated an unhandled asynchronous exception.", 
"details": "ReferenceError: auth0 is not defined", 
"name": "ReferenceError", 
"message": "auth0 is not defined", 
"stack": "ReferenceError: auth0 is not defined\n at module.exports (/data/io/0f9591a3-07e2-42ad-a60c-ba5591d84491/webtask.js:7:16)\n at Authz.is_authorized.error (/data/sandbox/node_modules/auth0-ext-compilers/lib/compilers/user-registration.js:30:16)\n at Object.is_authorized (/data/sandbox/node_modules/auth0-ext-compilers/lib/authorization.js:13:81)\n at userRegistrationHandler (/data/sandbox/node_modules/auth0-ext-compilers/lib/compilers/user-registration.js:9:18)\n at parseBody (/data/sandbox/node_modules/auth0-ext-compilers/lib/adapter.js:90:20)\n at finish (/data/sandbox/node_modules/auth0-ext-compilers/node_modules/wreck/lib/index.js:369:16)\n at wrapped (/data/sandbox/node_modules/auth0-ext-compilers/node_modules/hoek/lib/index.js:879:20)\n at module.exports.internals.Recorder.onReaderFinish (/data/sandbox/node_modules/auth0-ext-compilers/node_modules/wreck/lib/index.js:415:16)\n at Object.onceWrapper (events.js:313:30)\n at emitNone (events.js:111:20)\n at module.exports.internals.Recorder.emit (events.js:208:7)\n at finishMaybe (_stream_writable.js:613:14)\n at afterWrite (_stream_writable.js:464:3)\n at _combinedTickCallback (internal/process/next_tick.js:145:20)\n at process._tickDomainCallback (internal/process/next_tick.js:219:9)" }

Ok I see, recalling now:
auth0.accessToken and auth0.domain isn’t automatically available/injected in Hooks automatically as it’s in Rules.

Is it even possible to update the user data within a hook then?