feathers-authentication-management
Version:
Adds sign up verification, forgotten password reset, and other capabilities to local feathers-authentication
105 lines (104 loc) • 5.72 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resetPwdWithShortToken = exports.resetPwdWithLongToken = void 0;
const errors_1 = require("@feathersjs/errors");
const debug_1 = __importDefault(require("debug"));
const helpers_1 = require("../helpers");
const debug = (0, debug_1.default)('authLocalMgnt:resetPassword');
function resetPwdWithLongToken(options, resetToken, password, notifierOptions = {}, params) {
return __awaiter(this, void 0, void 0, function* () {
(0, helpers_1.ensureValuesAreStrings)(resetToken, password);
return yield resetPassword(options, { resetToken }, { resetToken }, password, notifierOptions, params);
});
}
exports.resetPwdWithLongToken = resetPwdWithLongToken;
function resetPwdWithShortToken(options, resetShortToken, identifyUser, password, notifierOptions = {}, params) {
return __awaiter(this, void 0, void 0, function* () {
(0, helpers_1.ensureValuesAreStrings)(resetShortToken, password);
(0, helpers_1.ensureObjPropsValid)(identifyUser, options.identifyUserProps);
return yield resetPassword(options, identifyUser, { resetShortToken }, password, notifierOptions, params);
});
}
exports.resetPwdWithShortToken = resetPwdWithShortToken;
function resetPassword(options, identifyUser, tokens, password, notifierOptions = {}, params) {
return __awaiter(this, void 0, void 0, function* () {
debug('resetPassword', identifyUser, tokens, password);
if (params && "query" in params) {
params = Object.assign({}, params);
delete params.query;
}
const { app, service, skipIsVerifiedCheck, reuseResetToken, passwordField, skipPasswordHash, sanitizeUserForClient, notifier } = options;
const usersService = app.service(service);
const usersServiceId = usersService.id;
let users;
if (tokens.resetToken) {
const id = (0, helpers_1.deconstructId)(tokens.resetToken);
const user = yield usersService.get(id, Object.assign({}, params));
users = [user];
}
else if (tokens.resetShortToken) {
users = (yield usersService.find(Object.assign(Object.assign({}, params), { query: Object.assign(Object.assign({}, identifyUser), { $limit: 2 }), paginate: false })));
}
else {
throw new errors_1.BadRequest('resetToken and resetShortToken are missing. (authLocalMgnt)', { errors: { $className: 'missingToken' } });
}
const checkProps = skipIsVerifiedCheck ? ['resetNotExpired'] : ['resetNotExpired', 'isVerified'];
const user = (0, helpers_1.getUserData)(users, checkProps);
// compare all tokens (hashed)
const tokenChecks = Object.keys(tokens).map((key) => __awaiter(this, void 0, void 0, function* () {
if (reuseResetToken) {
// Comparing token directly as reused resetToken is not hashed
if (tokens[key] !== user[key]) {
throw new errors_1.BadRequest('Reset Token is incorrect. (authLocalMgnt)', {
errors: { $className: 'incorrectToken' }
});
}
}
else {
return yield (0, helpers_1.comparePasswords)(tokens[key], user[key], () => new errors_1.BadRequest('Reset Token is incorrect. (authLocalMgnt)', { errors: { $className: 'incorrectToken' } }));
}
}));
try {
yield Promise.all(tokenChecks);
}
catch (err) {
// if token check fail, either decrease remaining attempts or cancel reset
if (user.resetAttempts > 0) {
yield usersService.patch(user[usersServiceId], {
resetAttempts: user.resetAttempts - 1
}, Object.assign({}, params));
throw err;
}
else {
yield usersService.patch(user[usersServiceId], {
resetToken: null,
resetAttempts: null,
resetShortToken: null,
resetExpires: null
}, Object.assign({}, params));
throw new errors_1.BadRequest('Invalid token. Get for a new one. (authLocalMgnt)', { errors: { $className: 'invalidToken' } });
}
}
const patchedUser = yield usersService.patch(user[usersServiceId], {
[passwordField]: skipPasswordHash ? password : yield (0, helpers_1.hashPassword)(app, password, passwordField),
resetExpires: null,
resetAttempts: null,
resetToken: null,
resetShortToken: null
}, Object.assign({}, params));
const userResult = yield (0, helpers_1.notify)(notifier, 'resetPwd', patchedUser, notifierOptions);
return sanitizeUserForClient(userResult);
});
}