feathersjs-ecosystem/feathers-authentication-management

verifyToken and others are empty

Closed this issue · 6 comments

jbatx commented

I followed this guide to set things up https://hackernoon.com/setting-up-email-verification-in-feathersjs-ce764907e4f2. email works, so, that's good. Now I'm working toward generating the verifyToken url. The part that's not working is setting the token in the URL. The tokens are not on the user by the time the url is generated.

Admittedly, I'm tired. Hopefully I'm just missing something simple.

note: I'm hitting users.create from another service called signup sign up has no auth on it. signup.create keeps a record of the sign up and any other details that may not be involved in the actual user model. Organization name, for example.

I can see that the tokens are getting created and added to the object in verifyHooks.addVerification(). Here's a screenshot of the state of hook just before it's returned. https://www.evernote.com/l/ADodJylat31J77RtYMYJpF4i6K8rwet-DtY

As you can see, the verifyToken is there. Here is the list of user before create hooks:

create: [hashPassword('password'), authenticate('jwt'), userCreateValidator(), verifyHooks.addVerification()],

I have stripped this down to hashPassword('password'), verifyHooks.addVerification() and tested. The behavior is the same.

Here is the state of context.data just before triggering the resendVerifySignup case in notifier.js https://www.evernote.com/l/ADoginovCKxK7KnbCiYHrYXP6y_m1UPVNQI

As you can see, they're on the context.data object.

Then, in the notifier.js, the values are gone. Here's another screenshot: https://www.evernote.com/l/ADpZVElyGWJNb5kjyo511XLsYUJHJwAtqnI

Here are the user after create hooks: create: [ addUserToOrg(), addUserToGroup(), context => { accountService(context.app).notifier('resendVerifySignup', context.result); }, verifyHooks.removeVerification()],

I have stripped this down to only context => { accountService(context.app).notifier('resendVerifySignup', context.result); }, verifyHooks.removeVerification() and tested. The behavior is the same.

other details...

`
node v12.16.3

"dependencies": {
"@feathersjs/authentication": "^4.5.3",
"@feathersjs/authentication-local": "^4.5.3",
"@feathersjs/authentication-oauth": "^4.5.3",
"@feathersjs/configuration": "^4.5.3",
"@feathersjs/errors": "^4.5.3",
"@feathersjs/express": "^4.5.3",
"@feathersjs/feathers": "^4.5.3",
"@feathersjs/socketio": "^4.5.3",
"@feathersjs/transport-commons": "^4.5.3",
"aws-sdk": "^2.673.0",
"compression": "^1.7.4",
"cors": "^2.8.5",
"feathers-authentication-management": "^2.0.1",
"feathers-hooks-common": "^5.0.3",
"feathers-mailer": "^3.0.1",
"feathers-sequelize": "^6.1.0",
"helmet": "^3.22.0",
"jwt-decode": "^2.2.0",
"node-redshift": "^0.1.5",
"nodemailer-smtp-transport": "^2.7.4",
"pg": "^8.0.3",
"sequelize": "^5.21.7",
"serve-favicon": "^2.5.0",
"winston": "^3.2.1"
},`

I wonder if the problem is not in the way you wrote the hook with the notifier, if you use brackets then you should use a return statement on the promise from the notifier, otherwise don't use brackets: context => accountService(context.app).notifier('resendVerifySignup', context.result). Indeed I guess the hook chain does not await the async notifier call so that the removeVerification hook is run before the actual processing of the notifier.

By the way in case you did not notice the removeVerification should also be used as an after get/find hook, the goal is to avoid getting the tokens on the client side.

jbatx commented

Hi @claustres, I think I see the issue. While addVerification adds the tokens to hook.data, the notifier is passed context.result which has no tokens. I suppose what is happening it that the user is getting created prior to the tokens existing in the data object - perhaps. This might be related to how I'm calling users.create from the signup service.

debugger screenshot: https://www.evernote.com/l/ADolpWZziz9FwIN8F9YV-vabZKOqE-67ps4

I removed the removed the removeVerification hook completely and retested. The same behavior persists.

re the removeVerification hook - thanks for the heads up. I had not finished the article yet. I'll add them there too.

This is a strange behavior, hook.result is what is returned by the DB adapter after the create so that if hook.data contains the tokens then it should as well, unless it is removed by another process.

jbatx commented

sequelize is building the insert like this INSERT INTO "users" ("id","email","password","createdAt","updatedAt") VALUES (DEFAULT,$1,$2,$3,$4)

after addVerification has returned.

My users model looks like this and the columns are in the table

`
const Sequelize = require('sequelize');
const DataTypes = Sequelize.DataTypes;

module.exports = function (app) {
const sequelizeClient = app.get('sequelizeClient');
const users = sequelizeClient.define('users', {

email: {
  type: DataTypes.STRING,
  allowNull: false,
  unique: true
},
password: {
  type: DataTypes.STRING,
  allowNull: false
},
googleId: { type: DataTypes.STRING },
githubId: { type: DataTypes.STRING },
isVerified: { type: DataTypes.BOOLEAN },
verifyToken: { type: DataTypes.STRING },
verifyExpires: { type: DataTypes.DATE },
verifyChanges: { type: DataTypes.JSON },
resetToken: { type: DataTypes.STRING },
resetExpires: { type: DataTypes.DATE },

}, {
hooks: {
beforeCount(options) {
options.raw = true;
}
}
});

users.associate = function (models) {
users.belongsToMany(models.organizations,{through: 'users_to_organizations'});
users.belongsToMany(models.groups, {through: 'users_to_groups'});
};

return users;
};
`

This is the signup after hook that creates the user

`module.exports = (options = {}) => {
return async context => {

const users = context.app.service('users');
const password = 'supersecret';
const user = {
  'email': context.data.email,
  'password': password,
};
users.create(user)
  .then()
  .catch((error) => {
    console.log(error);
  });

return context;

};
};
`

jbatx commented

I bypassed signup and posted a new user with

{
	"email": "emaily@email.com",
	"password": "supersecret"
}

The same behavior persisted

jbatx commented

solved... user error

I had some junk in the users.class.js that was changing the data object.