A 30-char token is generated suitable for URL responses.
(Configurable length.)
This may be embedded in URL links sent by email, SMS or social media
so that clicking the link starts the email address verification or the password reset.
A 6-digit token is also generated suitable for notification by SMS or social media.
(Configurable length, may be alpha-numeric instead.)
This may be manually entered in a UI to start the email address verification or the password reset.
The email verification token has a 5-day expiry (configurable),
while the password reset has a 2 hour expiry (configurable).
The server does not handle any interactions with the user.
Leaving it a pure API server, lets it be used with both native and browser clients.
Method calls return a Promise unless a callback is provided.
const verifyReset = app.service('verifyReset');
verifyReset.create({ action: 'checkUnique',
value: uniques,
ownId,
meta: { noErrMsg },
}, {}, cb)
verifyReset.create({ action: 'resendVerifySignup',
value: emailOrToken,
notifierOptions: {},
}, {}, cb)
verifyReset.create({ action: 'verifySignupLong',
value: token,
}, {}, cb)
verifyReset.create({ action: 'verifySignupShort',
value: {
token,
user: {}
}
}, {}, cb)
verifyReset.create({ action: 'sendResetPwd',
value: email,
notifierOptions: {},
}, {}, cb)
verifyReset.create({ action: 'resetPwdLong',
value: {
token,
password,
},
}, {}, cb)
verifyReset.create({ action: 'resetPwdShort',
value: {
token,
password,
user: {}
},
}, {}, cb)
verifyReset.create({ action: 'passwordChange',
value: {
oldPassword,
password,
},
}, { user }, cb)
verifyReset.create({ action: 'emailChange',
value: {
password,
email,
},
}, { user }, cb)
var cbCalled = false;
app.authenticate({ type: 'local', email, password })
.then((result) => {
const user = result.data;
if (!user || !user.isVerified) {
app.logout();
cb(new Error(user ? 'User\'s email is not verified.' : 'No user returned.'));
return;
}
cbCalled = true;
cb(null, user);
})
.catch((err) => {
if (!cbCalled) { cb(err); }
});
The wrappers return a Promise unless a callback is provided.
See example/
for a working example of wrapper usage.
```javascript`
or
import VerifyRest from 'feathers-service-verify-reset/lib/client';
const app = feathers() ...
const verifyReset = new VerifyReset(app);
// check props are unique in the users items
verifyReset.checkUnique(uniques, ownId, ifErrMsg, cb)
// resend email verification notification
verifyReset.resendVerifySignup(emailOrToken, notifierOptions, cb)
// email addr verification with long token
verifyReset.verifySignupLong(token, cb)
// email addr verification with short token
verifyReset.verifySignupShort(token, userFind, cb)
// send forgotten password notification
verifyReset.sendResetPwd(email, notifierOptions, cb)
// forgotten password verification with long token
verifyReset.resetPwdLong(token, password, cb)
// forgotten password verification with short token
verifyReset.resetPwdShort(token, userFind, password, cb)
// change password
verifyReset.passwordChange(oldPassword, password, user, cb)
// change email
verifyReset.emailChange(password, email, user, cb)
// Authenticate user and log on if user is verified.
verifyReset.authenticate(email, password, cb)
### <a name="fetch"> HTTP fetch (docs to complete)
```javascript
// check props are unique in the users items
// Set params just like [Feathers method calls.](#methods)
fetch('/verifyReset', {
method: 'POST', headers: { Accept: 'application/json' },
body: JSON.stringify({ action: 'checkUnique', value: uniques, ownId, meta: { noErrMsg } })
})
.then(data => { ... }).catch(err => { ... });
Hooks
The service does not itself handle creation of a new user account nor the sending of the initial
email verification request.
Instead hooks are provided for you to use with the users
service create
method.
const verifyHooks = require('feathers-service-verify-reset').verifyResetHooks;
module.exports.before = {
create: [
auth.hashPassword(),
verifyHooks.addVerification()
]
};
module.exports.after = {
create: [
hooks.remove('password'),
aHookToEmailYourVerification(),
verifyHooks.removeVerification()
]
};
A hook is provided to ensure the user's email addr is verified:
const auth = require('feathers-authentication').hooks;
const verify = require('feathers-service-verify-reset').hooks;
export.before = {
create: [
auth.verifyToken(),
auth.populateUser(),
auth.restrictToAuthenticated(),
verify.isVerified()
]
};
An email to verify the user's email addr can be sent when user if created on the server,
e.g. example/src/services/user/hooks/index
:
The client handles all interactions with the user.
Therefore the server must serve the client app when, for example, a URL link is followed
for email addr verification.
The client must do some routing based on the path in the link.
Assume you have sent the email link:
http://localhost:3030/socket/verify/12b827994bb59cacce47978567989e
The server serves the client app on /socket
:
app.use('/', serveStatic(app.get('public')))
.use('/socket', (req, res) => {
res.sendFile(path.resolve(__dirname, '..', 'public', 'socket.html'));
})
The client then routes itself based on the URL.
You will likely use you favorite client-side router,
but a primitive routing would be:
const [leader, provider, action, slug] = window.location.pathname.split('/');
switch (action) {
case 'verify':
verifySignUp(slug);
break;
case 'reset':
resetPassword(slug);
break;
default:
}
A few changes are needed to migrate to 1.0.0. Names were standardized throughout the
new version and these had to be changed.
options1.notifier signature
was (type, user1, params, cb)
now (type, user1, notifierOptions, newEmail, cb)
options1.notifier param 'type'
'resend' now 'resendVerifySignup'
'verify' now 'verifySignup'
'forgot' now 'sendResetPwd'
'reset' now 'resetPwd'
'password' now 'passwordChange'
'email' now 'emailChange'
Error messages used to return
new errors.BadRequest('Password is incorrect.',
{ errors: { password: 'Password is incorrect.' } })
This was hacky although convenient if the names matched your UI. Now they return
new errors.BadRequest('Password is incorrect.',
{ errors: { password: 'Password is incorrect.', $className: 'badParams' } })
or even
new errors.BadRequest('Password is incorrect.',
{ errors: { $className: 'badParams' } })
Set your local UI errors based on the $className value.
The following are deprecated but remain working. They will be removed in the future.
options1
emailer uses options1.notifier
API param 'action'
'unique' uses 'checkUnique'
'resend' uses 'resendVerifySignup'
'verify' uses 'verifySignupLong'
'forgot' uses 'sendResetPwd'
'reset' uses 'resetPwdLong'
'password' uses 'passwordChange'
'email' uses 'emailChange'
client wrapper
.unique uses .checkUnique
.verifySignUp uses .verifySignupLong
.sendResetPassword uses .sendResetPwd
.saveResetPassword uses .resetPwdLong
.changePassword uses .passwordChange
.changeEmail uses .emailChange
The service now uses the route /verifyreset rather than /verifyReset/:action/:value
You can then require the utilities.
MIT. See LICENSE.