verifyToken and others are empty
Closed this issue · 6 comments
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.
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.
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;
};
};
`
I bypassed signup and posted a new user with
{
"email": "emaily@email.com",
"password": "supersecret"
}
The same behavior persisted
solved... user error
I had some junk in the users.class.js that was changing the data object.