New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@accounts/server

Package Overview
Dependencies
Maintainers
5
Versions
204
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@accounts/server - npm Package Compare versions

Comparing version

to
0.1.0-alpha.fe08f703

lib/config.d.ts

103

lib/accounts-server.d.ts

@@ -1,26 +0,83 @@

import { UserObjectType, LoginReturnType } from '@accounts/common';
import { ConnectionInformationsType, DBInterface } from './types';
export interface AccountsServerOptions {
db: DBInterface;
tokenSecret: string;
tokenConfigs?: {
accessToken?: {
expiresIn?: string;
};
refreshToken?: {
expiresIn?: string;
};
};
/// <reference types="@types/node" />
import { EventEmitter } from 'events';
import { UserObjectType, CreateUserType, PasswordLoginUserType, LoginReturnType, TokensType, SessionType, ImpersonateReturnType, PasswordType, HookListener } from '@accounts/common';
import { AccountsServerConfiguration, PasswordAuthenticator } from './config';
import { DBInterface } from './db-interface';
export interface TokenRecord {
token: string;
address: string;
when: number;
reason: string;
}
export default class AccountsServer {
private services;
export declare type RemoveListnerHandle = () => EventEmitter;
export declare const ServerHooks: {
LoginSuccess: string;
LoginError: string;
LogoutSuccess: string;
LogoutError: string;
CreateUserSuccess: string;
CreateUserError: string;
ResumeSessionSuccess: string;
ResumeSessionError: string;
RefreshTokensSuccess: string;
RefreshTokensError: string;
ImpersonationSuccess: string;
ImpersonationError: string;
};
export declare class AccountsServer {
private _options;
private db;
private options;
constructor(services: any, options: AccountsServerOptions);
loginWithService(serviceName: string, params: any, infos: ConnectionInformationsType): Promise<LoginReturnType>;
loginWithUser(user: UserObjectType, infos: ConnectionInformationsType): Promise<LoginReturnType>;
resumeSession(accessToken: string): Promise<UserObjectType | null>;
private findSessionByAccessToken(accessToken);
private createTokens(sessionId, isImpersonated?);
private sanitizeUser(user);
private email;
private emailTemplates;
private hooks;
config(options: AccountsServerConfiguration, db: DBInterface): void;
options(): AccountsServerConfiguration;
onLoginSuccess(callback: HookListener): RemoveListnerHandle;
onLoginError(callback: HookListener): RemoveListnerHandle;
onLogoutSuccess(callback: HookListener): RemoveListnerHandle;
onLogoutError(callback: HookListener): RemoveListnerHandle;
onCreateUserSuccess(callback: HookListener): RemoveListnerHandle;
onCreateUserError(callback: HookListener): RemoveListnerHandle;
onResumeSessionSuccess(callback: HookListener): RemoveListnerHandle;
onResumeSessionError(callback: HookListener): RemoveListnerHandle;
onRefreshTokensSuccess(callback: HookListener): RemoveListnerHandle;
onRefreshTokensError(callback: HookListener): RemoveListnerHandle;
onImpersonationSuccess(callback: HookListener): RemoveListnerHandle;
onImpersonationError(callback: HookListener): RemoveListnerHandle;
loginWithPassword(user: PasswordLoginUserType, password: PasswordType, ip: string, userAgent: string): Promise<LoginReturnType>;
_externalPasswordAuthenticator(authFn: PasswordAuthenticator, user: PasswordLoginUserType, password: PasswordType): Promise<any>;
loginWithUser(user: UserObjectType, ip?: string, userAgent?: string): Promise<LoginReturnType>;
createUser(user: CreateUserType): Promise<string>;
impersonate(accessToken: string, username: string, ip: string, userAgent: string): Promise<ImpersonateReturnType>;
refreshTokens(accessToken: string, refreshToken: string, ip: string, userAgent: string): Promise<LoginReturnType>;
createTokens(sessionId: string, isImpersonated?: boolean): TokensType;
logout(accessToken: string): Promise<void>;
resumeSession(accessToken: string): Promise<UserObjectType>;
findSessionByAccessToken(accessToken: string): Promise<SessionType>;
findUserByEmail(email: string): Promise<UserObjectType>;
findUserByUsername(username: string): Promise<UserObjectType>;
findUserById(userId: string): Promise<UserObjectType>;
addEmail(userId: string, newEmail: string, verified: boolean): Promise<void>;
removeEmail(userId: string, email: string): Promise<void>;
verifyEmail(token: string): Promise<void>;
resetPassword(token: string, newPassword: PasswordType): Promise<void>;
setPassword(userId: string, newPassword: string): Promise<void>;
setProfile(userId: string, profile: object): Promise<void>;
updateProfile(userId: string, profile: object): Promise<object>;
sendVerificationEmail(address: string): Promise<void>;
sendResetPasswordEmail(address: string): Promise<void>;
sendEnrollmentEmail(address: string): Promise<void>;
private _on(eventName, callback);
private _isTokenExpired(token, tokenRecord?);
private _internalUserSanitizer(user);
private _sanitizeUser(user);
private _prepareMail(to, token, user, pathFragment, emailTemplate, from);
private _defaultPrepareEmail(to, token, user, pathFragment, emailTemplate, from);
private _defaultCreateTokenizedUrl(pathFragment, token);
private _getFirstUserEmail(user, address);
private _hashAndBcryptPassword(password);
private _validateLoginWithField(fieldName, user);
private _defaultPasswordAuthenticator(user, password);
}
declare const _default: AccountsServer;
export default _default;

@@ -46,41 +46,126 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var lodash_1 = require("lodash");
var pick = require("lodash/pick");
var omit = require("lodash/omit");
var isString = require("lodash/isString");
var isPlainObject = require("lodash/isPlainObject");
var isFunction = require("lodash/isFunction");
var isArray = require("lodash/isArray");
var find = require("lodash/find");
var includes = require("lodash/includes");
var get = require("lodash/get");
var events_1 = require("events");
var jwt = require("jsonwebtoken");
var common_1 = require("@accounts/common");
var config_1 = require("./config");
var encryption_1 = require("./encryption");
var tokens_1 = require("./tokens");
var defaultOptions = {
tokenSecret: 'secret',
tokenConfigs: {
accessToken: {
expiresIn: '90m',
},
refreshToken: {
expiresIn: '7d',
},
},
var email_1 = require("./email");
var email_templates_1 = require("./email-templates");
exports.ServerHooks = {
LoginSuccess: 'LoginSuccess',
LoginError: 'LoginError',
LogoutSuccess: 'LogoutSuccess',
LogoutError: 'LogoutError',
CreateUserSuccess: 'CreateUserSuccess',
CreateUserError: 'CreateUserError',
ResumeSessionSuccess: 'ResumeSessionSuccess',
ResumeSessionError: 'ResumeSessionError',
RefreshTokensSuccess: 'RefreshTokensSuccess',
RefreshTokensError: 'RefreshTokensError',
ImpersonationSuccess: 'ImpersonationSuccess',
ImpersonationError: 'ImpersonationError',
};
var AccountsServer = (function () {
function AccountsServer(services, options) {
this.services = services;
this.options = __assign({}, defaultOptions, options);
this.db = this.options.db;
for (var service in this.services) {
this.services[service].db = this.db;
function AccountsServer() {
}
AccountsServer.prototype.config = function (options, db) {
this._options = __assign({}, config_1.default, options);
if (!db) {
throw new common_1.AccountsError('A database driver is required');
}
}
AccountsServer.prototype.loginWithService = function (serviceName, params, infos) {
this.db = db;
this.email = this._options.sendMail
? { sendMail: this._options.sendMail }
: new email_1.default(this._options.email);
this.emailTemplates = email_templates_1.default;
if (!this.hooks) {
this.hooks = new events_1.EventEmitter();
}
};
AccountsServer.prototype.options = function () {
return this._options;
};
AccountsServer.prototype.onLoginSuccess = function (callback) {
return this._on(exports.ServerHooks.LoginSuccess, callback);
};
AccountsServer.prototype.onLoginError = function (callback) {
return this._on(exports.ServerHooks.LoginError, callback);
};
AccountsServer.prototype.onLogoutSuccess = function (callback) {
return this._on(exports.ServerHooks.LogoutSuccess, callback);
};
AccountsServer.prototype.onLogoutError = function (callback) {
return this._on(exports.ServerHooks.LogoutError, callback);
};
AccountsServer.prototype.onCreateUserSuccess = function (callback) {
return this._on(exports.ServerHooks.CreateUserSuccess, callback);
};
AccountsServer.prototype.onCreateUserError = function (callback) {
return this._on(exports.ServerHooks.CreateUserError, callback);
};
AccountsServer.prototype.onResumeSessionSuccess = function (callback) {
return this._on(exports.ServerHooks.ResumeSessionSuccess, callback);
};
AccountsServer.prototype.onResumeSessionError = function (callback) {
return this._on(exports.ServerHooks.ResumeSessionError, callback);
};
AccountsServer.prototype.onRefreshTokensSuccess = function (callback) {
return this._on(exports.ServerHooks.RefreshTokensSuccess, callback);
};
AccountsServer.prototype.onRefreshTokensError = function (callback) {
return this._on(exports.ServerHooks.RefreshTokensError, callback);
};
AccountsServer.prototype.onImpersonationSuccess = function (callback) {
return this._on(exports.ServerHooks.ImpersonationSuccess, callback);
};
AccountsServer.prototype.onImpersonationError = function (callback) {
return this._on(exports.ServerHooks.ImpersonationError, callback);
};
AccountsServer.prototype.loginWithPassword = function (user, password, ip, userAgent) {
return __awaiter(this, void 0, void 0, function () {
var user;
var foundUser, loginResult, error_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!this.services[serviceName]) {
throw new Error("No service with the name " + serviceName + " was registered.");
_a.trys.push([0, 6, , 7]);
if (!user || !password) {
throw new common_1.AccountsError('Unrecognized options for login request', user, 400);
}
return [4, this.services[serviceName].authenticate(params)];
if ((!isString(user) && !isPlainObject(user)) || !isString(password)) {
throw new common_1.AccountsError('Match failed', user, 400);
}
foundUser = void 0;
if (!this._options.passwordAuthenticator) return [3, 2];
return [4, this._externalPasswordAuthenticator(this._options.passwordAuthenticator, user, password)];
case 1:
user = _a.sent();
if (!user) {
throw new Error("Service " + serviceName + " was not able to authenticate user");
foundUser = _a.sent();
return [3, 4];
case 2: return [4, this._defaultPasswordAuthenticator(user, password)];
case 3:
foundUser = _a.sent();
_a.label = 4;
case 4:
if (!foundUser) {
throw new common_1.AccountsError('User not found', user, 403);
}
return [2, this.loginWithUser(user, infos)];
return [4, this.loginWithUser(foundUser, ip, userAgent)];
case 5:
loginResult = _a.sent();
this.hooks.emit(exports.ServerHooks.LoginSuccess, loginResult);
return [2, loginResult];
case 6:
error_1 = _a.sent();
this.hooks.emit(exports.ServerHooks.LoginError, error_1);
throw error_1;
case 7: return [2];
}

@@ -90,10 +175,15 @@ });

};
AccountsServer.prototype.loginWithUser = function (user, infos) {
AccountsServer.prototype._externalPasswordAuthenticator = function (authFn, user, password) {
return __awaiter(this, void 0, void 0, function () {
var ip, userAgent, sessionId, _a, accessToken, refreshToken, loginResult;
return __generator(this, function (_a) {
return [2, authFn(user, password)];
});
});
};
AccountsServer.prototype.loginWithUser = function (user, ip, userAgent) {
return __awaiter(this, void 0, void 0, function () {
var sessionId, _a, accessToken, refreshToken, loginResult;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
ip = infos.ip, userAgent = infos.userAgent;
return [4, this.db.createSession(user.id, ip, userAgent)];
case 0: return [4, this.db.createSession(user.id, ip, userAgent)];
case 1:

@@ -104,3 +194,3 @@ sessionId = _b.sent();

sessionId: sessionId,
user: this.sanitizeUser(user),
user: this._sanitizeUser(user),
tokens: {

@@ -116,13 +206,93 @@ refreshToken: refreshToken,

};
AccountsServer.prototype.resumeSession = function (accessToken) {
AccountsServer.prototype.createUser = function (user) {
return __awaiter(this, void 0, void 0, function () {
var session, user, e_1;
var _a, _b, password, validateNewUser, proposedUserObject, userId, error_2;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_c.trys.push([0, 10, , 11]);
if (!common_1.validators.validateUsername(user.username) &&
!common_1.validators.validateEmail(user.email)) {
throw new common_1.AccountsError('Username or Email is required', {
username: user && user.username,
email: user && user.email,
});
}
_a = user.username;
if (!_a) return [3, 2];
return [4, this.db.findUserByUsername(user.username)];
case 1:
_a = (_c.sent());
_c.label = 2;
case 2:
if (_a) {
throw new common_1.AccountsError('Username already exists', {
username: user.username,
});
}
_b = user.email;
if (!_b) return [3, 4];
return [4, this.db.findUserByEmail(user.email)];
case 3:
_b = (_c.sent());
_c.label = 4;
case 4:
if (_b) {
throw new common_1.AccountsError('Email already exists', { email: user.email });
}
password = void 0;
if (!user.password) return [3, 6];
return [4, this._hashAndBcryptPassword(user.password)];
case 5:
password = _c.sent();
_c.label = 6;
case 6:
validateNewUser = this.options().validateNewUser;
proposedUserObject = {
username: user.username,
email: user.email && user.email.toLowerCase(),
password: password,
profile: user.profile,
};
if (!isFunction(validateNewUser)) return [3, 8];
return [4, validateNewUser(proposedUserObject)];
case 7:
_c.sent();
_c.label = 8;
case 8: return [4, this.db.createUser(proposedUserObject)];
case 9:
userId = _c.sent();
this.hooks.emit(exports.ServerHooks.CreateUserSuccess, userId, proposedUserObject);
return [2, userId];
case 10:
error_2 = _c.sent();
this.hooks.emit(exports.ServerHooks.CreateUserError, error_2);
throw error_2;
case 11: return [2];
}
});
});
};
AccountsServer.prototype.impersonate = function (accessToken, username, ip, userAgent) {
return __awaiter(this, void 0, void 0, function () {
var session, user, impersonatedUser, isAuthorized, newSessionId, impersonationTokens, impersonationResult, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 4, , 5]);
_a.trys.push([0, 6, , 7]);
if (!isString(accessToken)) {
throw new common_1.AccountsError('An access token is required');
}
try {
jwt.verify(accessToken, this._options.tokenSecret);
}
catch (err) {
throw new common_1.AccountsError('Access token is not valid');
}
return [4, this.findSessionByAccessToken(accessToken)];
case 1:
session = _a.sent();
if (!session.valid) return [3, 3];
if (!session.valid) {
throw new common_1.AccountsError('Session is not valid for user');
}
return [4, this.db.findUserById(session.userId)];

@@ -132,10 +302,35 @@ case 2:

if (!user) {
throw new Error('User not found');
throw new common_1.AccountsError('User not found');
}
return [2, this.sanitizeUser(user)];
case 3: return [2, null];
return [4, this.db.findUserByUsername(username)];
case 3:
impersonatedUser = _a.sent();
if (!impersonatedUser) {
throw new common_1.AccountsError("User " + username + " not found");
}
if (!this._options.impersonationAuthorize) {
return [2, { authorized: false }];
}
return [4, this._options.impersonationAuthorize(user, impersonatedUser)];
case 4:
isAuthorized = _a.sent();
if (!isAuthorized) {
return [2, { authorized: false }];
}
return [4, this.db.createSession(impersonatedUser.id, ip, userAgent, { impersonatorUserId: user.id })];
case 5:
newSessionId = _a.sent();
impersonationTokens = this.createTokens(newSessionId, true);
impersonationResult = {
authorized: true,
tokens: impersonationTokens,
user: this._sanitizeUser(impersonatedUser),
};
this.hooks.emit(exports.ServerHooks.ImpersonationSuccess, user, impersonationResult);
return [2, impersonationResult];
case 6:
e_1 = _a.sent();
this.hooks.emit(exports.ServerHooks.ImpersonationError, e_1);
throw e_1;
case 5: return [2];
case 7: return [2];
}

@@ -145,17 +340,22 @@ });

};
AccountsServer.prototype.findSessionByAccessToken = function (accessToken) {
AccountsServer.prototype.refreshTokens = function (accessToken, refreshToken, ip, userAgent) {
return __awaiter(this, void 0, void 0, function () {
var sessionId, decodedAccessToken, session;
var sessionId, decodedAccessToken, session, user, tokens, result, err_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!lodash_1.isString(accessToken)) {
throw new Error('An accessToken is required');
_a.trys.push([0, 6, , 7]);
if (!isString(accessToken) || !isString(refreshToken)) {
throw new common_1.AccountsError('An accessToken and refreshToken are required');
}
sessionId = void 0;
try {
decodedAccessToken = jwt.verify(accessToken, this.options.tokenSecret);
jwt.verify(refreshToken, this._options.tokenSecret);
decodedAccessToken = jwt.verify(accessToken, this._options.tokenSecret, {
ignoreExpiration: true,
});
sessionId = decodedAccessToken.data.sessionId;
}
catch (err) {
throw new Error('Tokens are not valid');
throw new common_1.AccountsError('Tokens are not valid');
}

@@ -166,5 +366,31 @@ return [4, this.db.findSessionById(sessionId)];

if (!session) {
throw new Error('Session not found');
throw new common_1.AccountsError('Session not found');
}
return [2, session];
if (!session.valid) return [3, 4];
return [4, this.db.findUserById(session.userId)];
case 2:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { id: session.userId });
}
tokens = this.createTokens(sessionId);
return [4, this.db.updateSession(sessionId, ip, userAgent)];
case 3:
_a.sent();
result = {
sessionId: sessionId,
user: this._sanitizeUser(user),
tokens: tokens,
};
this.hooks.emit(exports.ServerHooks.RefreshTokensSuccess, result);
return [2, result];
case 4: throw new common_1.AccountsError('Session is no longer valid', {
id: session.userId,
});
case 5: return [3, 7];
case 6:
err_1 = _a.sent();
this.hooks.emit(exports.ServerHooks.RefreshTokensError, err_1);
throw err_1;
case 7: return [2];
}

@@ -176,3 +402,3 @@ });

if (isImpersonated === void 0) { isImpersonated = false; }
var _a = this.options, tokenSecret = _a.tokenSecret, tokenConfigs = _a.tokenConfigs;
var _a = this._options, _b = _a.tokenSecret, tokenSecret = _b === void 0 ? config_1.default.tokenSecret : _b, _c = _a.tokenConfigs, tokenConfigs = _c === void 0 ? config_1.default.tokenConfigs : _c;
var accessToken = tokens_1.generateAccessToken({

@@ -184,16 +410,445 @@ data: {

secret: tokenSecret,
config: tokenConfigs.accessToken,
config: tokenConfigs.accessToken || {},
});
var refreshToken = tokens_1.generateRefreshToken({
secret: tokenSecret,
config: tokenConfigs.refreshToken,
config: tokenConfigs.refreshToken || {},
});
return { accessToken: accessToken, refreshToken: refreshToken };
};
AccountsServer.prototype.sanitizeUser = function (user) {
return lodash_1.omit(user, ['services']);
AccountsServer.prototype.logout = function (accessToken) {
return __awaiter(this, void 0, void 0, function () {
var session, user, error_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 6, , 7]);
return [4, this.findSessionByAccessToken(accessToken)];
case 1:
session = _a.sent();
if (!session.valid) return [3, 4];
return [4, this.db.findUserById(session.userId)];
case 2:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { id: session.userId });
}
return [4, this.db.invalidateSession(session.sessionId)];
case 3:
_a.sent();
this.hooks.emit(exports.ServerHooks.LogoutSuccess, this._sanitizeUser(user), session, accessToken);
return [3, 5];
case 4: throw new common_1.AccountsError('Session is no longer valid', {
id: session.userId,
});
case 5: return [3, 7];
case 6:
error_3 = _a.sent();
this.hooks.emit(exports.ServerHooks.LogoutError, error_3);
throw error_3;
case 7: return [2];
}
});
});
};
AccountsServer.prototype.resumeSession = function (accessToken) {
return __awaiter(this, void 0, void 0, function () {
var session, user, e_2, e_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 8, , 9]);
return [4, this.findSessionByAccessToken(accessToken)];
case 1:
session = _a.sent();
if (!session.valid) return [3, 7];
return [4, this.db.findUserById(session.userId)];
case 2:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { id: session.userId });
}
if (!this._options.resumeSessionValidator) return [3, 6];
_a.label = 3;
case 3:
_a.trys.push([3, 5, , 6]);
return [4, this._options.resumeSessionValidator(user, session)];
case 4:
_a.sent();
return [3, 6];
case 5:
e_2 = _a.sent();
throw new common_1.AccountsError(e_2, { id: session.userId }, 403);
case 6:
this.hooks.emit(exports.ServerHooks.ResumeSessionSuccess, user, accessToken);
return [2, this._sanitizeUser(user)];
case 7:
this.hooks.emit(exports.ServerHooks.ResumeSessionError, new common_1.AccountsError('Invalid Session', { id: session.userId }));
return [2, null];
case 8:
e_3 = _a.sent();
this.hooks.emit(exports.ServerHooks.ResumeSessionError, e_3);
throw e_3;
case 9: return [2];
}
});
});
};
AccountsServer.prototype.findSessionByAccessToken = function (accessToken) {
return __awaiter(this, void 0, void 0, function () {
var sessionId, decodedAccessToken, session;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!isString(accessToken)) {
throw new common_1.AccountsError('An accessToken is required');
}
try {
decodedAccessToken = jwt.verify(accessToken, this._options.tokenSecret);
sessionId = decodedAccessToken.data.sessionId;
}
catch (err) {
throw new common_1.AccountsError('Tokens are not valid');
}
return [4, this.db.findSessionById(sessionId)];
case 1:
session = _a.sent();
if (!session) {
throw new common_1.AccountsError('Session not found');
}
return [2, session];
}
});
});
};
AccountsServer.prototype.findUserByEmail = function (email) {
return this.db.findUserByEmail(email);
};
AccountsServer.prototype.findUserByUsername = function (username) {
return this.db.findUserByUsername(username);
};
AccountsServer.prototype.findUserById = function (userId) {
return this.db.findUserById(userId);
};
AccountsServer.prototype.addEmail = function (userId, newEmail, verified) {
return this.db.addEmail(userId, newEmail, verified);
};
AccountsServer.prototype.removeEmail = function (userId, email) {
return this.db.removeEmail(userId, email);
};
AccountsServer.prototype.verifyEmail = function (token) {
return __awaiter(this, void 0, void 0, function () {
var user, verificationTokens, tokenRecord, emailRecord;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserByEmailVerificationToken(token)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('Verify email link expired');
}
verificationTokens = get(user, ['services', 'email', 'verificationTokens'], []);
tokenRecord = find(verificationTokens, function (t) { return t.token === token; });
if (!tokenRecord) {
throw new common_1.AccountsError('Verify email link expired');
}
emailRecord = find(user.emails, function (e) { return e.address === tokenRecord.address; });
if (!emailRecord) {
throw new common_1.AccountsError('Verify email link is for unknown address');
}
return [4, this.db.verifyEmail(user.id, emailRecord.address)];
case 2:
_a.sent();
return [2];
}
});
});
};
AccountsServer.prototype.resetPassword = function (token, newPassword) {
return __awaiter(this, void 0, void 0, function () {
var user, resetTokens, asArray, resetTokenRecord, emails, tokenAddress, password;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserByResetPasswordToken(token)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('Reset password link expired');
}
resetTokens = get(user, ['services', 'password', 'reset'], []);
asArray = isArray(resetTokens) ? resetTokens : [resetTokens];
resetTokenRecord = find(asArray, function (t) { return t.token === token; });
if (this._isTokenExpired(token, resetTokenRecord)) {
throw new common_1.AccountsError('Reset password link expired');
}
emails = user.emails || [];
tokenAddress = resetTokenRecord.email || resetTokenRecord.address;
if (!includes(emails.map(function (email) { return email.address; }), tokenAddress)) {
throw new common_1.AccountsError('Token has invalid email address');
}
return [4, this._hashAndBcryptPassword(newPassword)];
case 2:
password = _a.sent();
return [4, this.db.setResetPasssword(user.id, resetTokenRecord.address, password, token)];
case 3:
_a.sent();
this.db.invalidateAllSessions(user.id);
return [2];
}
});
});
};
AccountsServer.prototype.setPassword = function (userId, newPassword) {
return __awaiter(this, void 0, void 0, function () {
var password;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, encryption_1.bcryptPassword(newPassword)];
case 1:
password = _a.sent();
return [2, this.db.setPasssword(userId, password)];
}
});
});
};
AccountsServer.prototype.setProfile = function (userId, profile) {
return __awaiter(this, void 0, void 0, function () {
var user;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserById(userId)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { id: userId });
}
return [4, this.db.setProfile(userId, profile)];
case 2:
_a.sent();
return [2];
}
});
});
};
AccountsServer.prototype.updateProfile = function (userId, profile) {
return __awaiter(this, void 0, void 0, function () {
var user;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserById(userId)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { id: userId });
}
return [2, this.db.setProfile(userId, __assign({}, user.profile, profile))];
}
});
});
};
AccountsServer.prototype.sendVerificationEmail = function (address) {
return __awaiter(this, void 0, void 0, function () {
var user, email, emails, token, resetPasswordMail;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserByEmail(address)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { email: address });
}
if (!address) {
email = find(user.emails, function (e) { return !e.verified; });
address = email && email.address;
}
emails = user.emails || [];
if (!address || !includes(emails.map(function (email) { return email.address; }), address)) {
throw new common_1.AccountsError('No such email address for user');
}
token = tokens_1.generateRandomToken();
return [4, this.db.addEmailVerificationToken(user.id, address, token)];
case 2:
_a.sent();
resetPasswordMail = this._prepareMail(address, token, this._sanitizeUser(user), 'verify-email', this.emailTemplates.verifyEmail, this.emailTemplates.from);
return [4, this.email.sendMail(resetPasswordMail)];
case 3:
_a.sent();
return [2];
}
});
});
};
AccountsServer.prototype.sendResetPasswordEmail = function (address) {
return __awaiter(this, void 0, void 0, function () {
var user, token, resetPasswordMail;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserByEmail(address)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { email: address });
}
address = this._getFirstUserEmail(user, address);
token = tokens_1.generateRandomToken();
return [4, this.db.addResetPasswordToken(user.id, address, token)];
case 2:
_a.sent();
resetPasswordMail = this._prepareMail(address, token, this._sanitizeUser(user), 'reset-password', this.emailTemplates.resetPassword, this.emailTemplates.from);
return [4, this.email.sendMail(resetPasswordMail)];
case 3:
_a.sent();
return [2];
}
});
});
};
AccountsServer.prototype.sendEnrollmentEmail = function (address) {
return __awaiter(this, void 0, void 0, function () {
var user, token, enrollmentMail;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4, this.db.findUserByEmail(address)];
case 1:
user = _a.sent();
if (!user) {
throw new common_1.AccountsError('User not found', { email: address });
}
address = this._getFirstUserEmail(user, address);
token = tokens_1.generateRandomToken();
return [4, this.db.addResetPasswordToken(user.id, address, token, 'enroll')];
case 2:
_a.sent();
enrollmentMail = this._prepareMail(address, token, this._sanitizeUser(user), 'enroll-account', this.emailTemplates.enrollAccount, this.emailTemplates.from);
return [4, this.email.sendMail(enrollmentMail)];
case 3:
_a.sent();
return [2];
}
});
});
};
AccountsServer.prototype._on = function (eventName, callback) {
var _this = this;
this.hooks.on(eventName, callback);
return function () { return _this.hooks.removeListener(eventName, callback); };
};
AccountsServer.prototype._isTokenExpired = function (token, tokenRecord) {
return (!tokenRecord ||
Number(tokenRecord.when) + this._options.emailTokensExpiry < Date.now());
};
AccountsServer.prototype._internalUserSanitizer = function (user) {
return omit(user, ['services']);
};
AccountsServer.prototype._sanitizeUser = function (user) {
var userObjectSanitizer = this.options().userObjectSanitizer;
return userObjectSanitizer(this._internalUserSanitizer(user), omit, pick);
};
AccountsServer.prototype._prepareMail = function (to, token, user, pathFragment, emailTemplate, from) {
if (this._options.prepareMail) {
return this._options.prepareMail(to, token, user, pathFragment, emailTemplate, from);
}
return this._defaultPrepareEmail(to, token, user, pathFragment, emailTemplate, from);
};
AccountsServer.prototype._defaultPrepareEmail = function (to, token, user, pathFragment, emailTemplate, from) {
var tokenizedUrl = this._defaultCreateTokenizedUrl(pathFragment, token);
return {
from: emailTemplate.from || from,
to: to,
subject: emailTemplate.subject(user),
text: emailTemplate.text(user, tokenizedUrl),
};
};
AccountsServer.prototype._defaultCreateTokenizedUrl = function (pathFragment, token) {
var siteUrl = this._options.siteUrl || config_1.default.siteUrl;
return siteUrl + "/" + pathFragment + "/" + token;
};
AccountsServer.prototype._getFirstUserEmail = function (user, address) {
if (!address && user.emails && user.emails[0]) {
address = user.emails[0].address;
}
var emails = user.emails || [];
if (!address ||
!includes(emails.map(function (email) { return email.address; }), address)) {
throw new common_1.AccountsError('No such email address for user');
}
return address;
};
AccountsServer.prototype._hashAndBcryptPassword = function (password) {
return __awaiter(this, void 0, void 0, function () {
var hashAlgorithm, hashedPassword;
return __generator(this, function (_a) {
hashAlgorithm = this._options.passwordHashAlgorithm;
hashedPassword = hashAlgorithm
? encryption_1.hashPassword(password, hashAlgorithm)
: password;
return [2, encryption_1.bcryptPassword(hashedPassword)];
});
});
};
AccountsServer.prototype._validateLoginWithField = function (fieldName, user) {
var allowedFields = this._options.allowedLoginFields || [];
var isAllowed = allowedFields.includes(fieldName);
if (!isAllowed) {
throw new common_1.AccountsError("Login with " + fieldName + " is not allowed!", user);
}
};
AccountsServer.prototype._defaultPasswordAuthenticator = function (user, password) {
return __awaiter(this, void 0, void 0, function () {
var _a, username, email, id, foundUser, hash, hashAlgorithm, pass, isPasswordValid;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_a = isString(user)
? common_1.toUsernameAndEmail({ user: user })
: common_1.toUsernameAndEmail(__assign({}, user)), username = _a.username, email = _a.email, id = _a.id;
if (!id) return [3, 2];
this._validateLoginWithField('id', user);
return [4, this.db.findUserById(id)];
case 1:
foundUser = _b.sent();
return [3, 6];
case 2:
if (!username) return [3, 4];
this._validateLoginWithField('username', user);
return [4, this.db.findUserByUsername(username)];
case 3:
foundUser = _b.sent();
return [3, 6];
case 4:
if (!email) return [3, 6];
this._validateLoginWithField('email', user);
return [4, this.db.findUserByEmail(email)];
case 5:
foundUser = _b.sent();
_b.label = 6;
case 6:
if (!foundUser) {
throw new common_1.AccountsError('User not found', user, 403);
}
return [4, this.db.findPasswordHash(foundUser.id)];
case 7:
hash = _b.sent();
if (!hash) {
throw new common_1.AccountsError('User has no password set', user, 403);
}
hashAlgorithm = this._options.passwordHashAlgorithm;
pass = hashAlgorithm
? encryption_1.hashPassword(password, hashAlgorithm)
: password;
return [4, encryption_1.verifyPassword(pass, hash)];
case 8:
isPasswordValid = _b.sent();
if (!isPasswordValid) {
throw new common_1.AccountsError('Incorrect password', user, 403);
}
return [2, foundUser];
}
});
});
};
return AccountsServer;
}());
exports.default = AccountsServer;
exports.AccountsServer = AccountsServer;
exports.default = new AccountsServer();
//# sourceMappingURL=accounts-server.js.map

@@ -1,3 +0,6 @@

import AccountsServer from './accounts-server';
export { DBInterface } from './types';
export { AccountsServer };
import Accounts, { AccountsServer } from './accounts-server';
import * as encryption from './encryption';
import { DBInterface } from './db-interface';
import config from './config';
export default Accounts;
export { AccountsServer, encryption, config, DBInterface };
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var accounts_server_1 = require("./accounts-server");
exports.AccountsServer = accounts_server_1.default;
exports.AccountsServer = accounts_server_1.AccountsServer;
var encryption = require("./encryption");
exports.encryption = encryption;
var config_1 = require("./config");
exports.config = config_1.default;
exports.default = accounts_server_1.default;
//# sourceMappingURL=index.js.map

@@ -6,3 +6,3 @@ export declare const generateRandomToken: (length?: number) => string;

config: object;
}) => any;
}) => string;
export declare const generateRefreshToken: ({secret, data, config}: {

@@ -12,2 +12,2 @@ secret: string;

config: object;
}) => any;
}) => string;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var jwt = require("jsonwebtoken");
var crypto = require("crypto");
var crypto_1 = require("crypto");
exports.generateRandomToken = function (length) {
if (length === void 0) { length = 43; }
return crypto.randomBytes(length).toString('hex');
return crypto_1.randomBytes(length).toString('hex');
};

@@ -9,0 +9,0 @@ exports.generateAccessToken = function (_a) {

{
"name": "@accounts/server",
"version": "0.1.0-alpha.f9ef5e7f",
"license": "MIT",
"version": "0.1.0-alpha.fe08f703",
"description": "Fullstack authentication and accounts-management",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"publishConfig": {
"access": "public"
},
"scripts": {
"start": "tsc --watch",
"start": "webpack -p --config --progress --watch",
"clean": "rimraf lib",
"precompile": "npm run clean",
"compile": "tsc",
"prepublish": "npm run compile",
"test": "npm run testonly",
"test-ci": "npm lint && npm coverage",
"testonly": "jest",
"coverage": "jest --coverage"
"coverage": "npm run testonly -- --coverage",
"coveralls": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"
},
"jest": {
"transform": {
".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
".(ts|tsx)": "<rootDir>/../../node_modules/ts-jest/preprocessor.js"
},
"testRegex": "./__tests__/.*.(ts|tsx)$",
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx)$",
"moduleFileExtensions": [
"ts",
"tsx",
"js"

@@ -24,8 +33,34 @@ ],

},
"repository": {
"type": "git",
"url": "https://github.com/js-accounts/accounts/tree/master/packages/server"
},
"keywords": [
"rest",
"graphql",
"grant",
"auth",
"authentication",
"accounts",
"users",
"oauth"
],
"author": "Tim Mikeladze",
"license": "MIT",
"dependencies": {
"jsonwebtoken": "^7.4.1"
"@accounts/common": "^0.1.0-alpha.fe08f703",
"babel-polyfill": "^6.23.0",
"bcryptjs": "^2.4.0",
"crypto": "^0.0.3",
"emailjs": "^1.0.8",
"jsonwebtoken": "^7.2.1",
"jwt-decode": "^2.1.0",
"lodash": "^4.16.4"
},
"peerDependencies": {
"@accounts/common": "^0.1.0"
"devDependencies": {
"coveralls": "^2.11.14",
"jest": "^18.0.0",
"localstorage-polyfill": "^1.0.1",
"rimraf": "^2.6.1"
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet