@accounts/server
Advanced tools
Comparing version 0.27.0 to 0.28.0-alpha.0
import Emittery from 'emittery'; | ||
import { User, LoginResult, Tokens, Session, ImpersonationUserIdentity, ImpersonationResult, HookListener, AuthenticationService, ConnectionInformations } from '@accounts/types'; | ||
import { User, LoginResult, Tokens, Session, ImpersonationUserIdentity, ImpersonationResult, HookListener, AuthenticationService, AuthenticatorService, ConnectionInformations, AuthenticationResult } from '@accounts/types'; | ||
import { AccountsServerOptions } from './types/accounts-server-options'; | ||
import { EmailTemplateType } from './types/email-template-type'; | ||
import { AccountsMFA } from './accounts-mfa'; | ||
declare const defaultOptions: { | ||
@@ -22,6 +23,9 @@ ambiguousErrorMessages: boolean; | ||
useInternalUserObjectSanitizer: boolean; | ||
enforceMfaForLogin: boolean; | ||
}; | ||
export declare class AccountsServer<CustomUser extends User = User> { | ||
options: AccountsServerOptions<CustomUser> & typeof defaultOptions; | ||
mfa: AccountsMFA; | ||
private services; | ||
private authenticators; | ||
private db; | ||
@@ -31,2 +35,4 @@ private hooks; | ||
[key: string]: AuthenticationService<CustomUser>; | ||
}, authenticators?: { | ||
[key: string]: AuthenticatorService; | ||
}); | ||
@@ -36,3 +42,3 @@ getServices(): { | ||
}; | ||
getOptions(): AccountsServerOptions; | ||
getOptions(): AccountsServerOptions<CustomUser>; | ||
getHooks(): Emittery; | ||
@@ -57,3 +63,3 @@ /** | ||
*/ | ||
loginWithService(serviceName: string, params: any, infos: ConnectionInformations): Promise<LoginResult>; | ||
loginWithService(serviceName: string, params: any, infos: ConnectionInformations): Promise<AuthenticationResult>; | ||
/** | ||
@@ -136,2 +142,5 @@ * @description Server use only. | ||
sanitizeUser(user: CustomUser): CustomUser; | ||
/** | ||
* Private methods | ||
*/ | ||
private internalUserSanitizer; | ||
@@ -138,0 +147,0 @@ private defaultPrepareEmail; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.AccountsServer = void 0; | ||
var tslib_1 = require("tslib"); | ||
@@ -12,2 +13,3 @@ var lodash_1 = require("lodash"); | ||
var errors_1 = require("./errors"); | ||
var accounts_mfa_1 = require("./accounts-mfa"); | ||
var defaultOptions = { | ||
@@ -30,5 +32,6 @@ ambiguousErrorMessages: true, | ||
useInternalUserObjectSanitizer: true, | ||
enforceMfaForLogin: false, | ||
}; | ||
var AccountsServer = /** @class */ (function () { | ||
function AccountsServer(options, services) { | ||
function AccountsServer(options, services, authenticators) { | ||
this.options = lodash_1.merge(tslib_1.__assign({}, defaultOptions), options); | ||
@@ -45,2 +48,3 @@ if (!this.options.db) { | ||
this.services = services || {}; | ||
this.authenticators = authenticators || {}; | ||
this.db = this.options.db; | ||
@@ -52,2 +56,9 @@ // Set the db to all services | ||
} | ||
// Set the db to all authenticators | ||
for (var service in this.authenticators) { | ||
this.authenticators[service].setStore(this.db); | ||
this.authenticators[service].server = this; | ||
} | ||
// Initialize the MFA module | ||
this.mfa = new accounts_mfa_1.AccountsMFA(this.options.db, authenticators); | ||
// Initialize hooks | ||
@@ -129,3 +140,3 @@ this.hooks = new emittery_1.default(); | ||
return tslib_1.__awaiter(this, void 0, void 0, function () { | ||
var hooksInfo, user, loginResult, err_2; | ||
var hooksInfo, mfaToken, mfaChallenge, authenticator, user_1, loginResult_1, user, authenticators, activeAuthenticator, mfaChallengeToken, mfaChallengeToken, loginResult, err_2; | ||
return tslib_1.__generator(this, function (_a) { | ||
@@ -144,3 +155,58 @@ switch (_a.label) { | ||
case 1: | ||
_a.trys.push([1, 5, , 6]); | ||
_a.trys.push([1, 20, , 21]); | ||
if (!(serviceName === 'mfa')) return [3 /*break*/, 11]; | ||
mfaToken = params.mfaToken; | ||
if (!mfaToken) { | ||
throw new Error('Mfa token is required'); | ||
} | ||
return [4 /*yield*/, this.db.findMfaChallengeByToken(mfaToken)]; | ||
case 2: | ||
mfaChallenge = _a.sent(); | ||
if (!mfaChallenge || !mfaChallenge.authenticatorId) { | ||
throw new Error('Mfa token invalid'); | ||
} | ||
return [4 /*yield*/, this.db.findAuthenticatorById(mfaChallenge.authenticatorId)]; | ||
case 3: | ||
authenticator = _a.sent(); | ||
if (!authenticator) { | ||
throw new Error('Mfa token invalid'); | ||
} | ||
if (!this.authenticators[authenticator.type]) { | ||
throw new Error("No authenticator with the name " + serviceName + " was registered."); | ||
} | ||
return [4 /*yield*/, this.authenticators[authenticator.type].authenticate(mfaChallenge, authenticator, params, infos)]; | ||
case 4: | ||
// TODO we need to implement some time checking for the mfaToken (eg: expire after X minutes, probably based on the authenticator configuration) | ||
if (!(_a.sent())) { | ||
throw new Error("Authenticator " + authenticator.type + " was not able to authenticate user"); | ||
} | ||
if (!(!authenticator.active && mfaChallenge.scope === 'associate')) return [3 /*break*/, 6]; | ||
return [4 /*yield*/, this.db.activateAuthenticator(authenticator.id)]; | ||
case 5: | ||
_a.sent(); | ||
return [3 /*break*/, 7]; | ||
case 6: | ||
if (!authenticator.active) { | ||
throw new Error('Authenticator is not active'); | ||
} | ||
_a.label = 7; | ||
case 7: | ||
// We invalidate the current mfa challenge so it can't be reused later | ||
return [4 /*yield*/, this.db.deactivateMfaChallenge(mfaChallenge.id)]; | ||
case 8: | ||
// We invalidate the current mfa challenge so it can't be reused later | ||
_a.sent(); | ||
return [4 /*yield*/, this.db.findUserById(mfaChallenge.userId)]; | ||
case 9: | ||
user_1 = _a.sent(); | ||
if (!user_1) { | ||
throw new Error('user not found'); | ||
} | ||
hooksInfo.user = user_1; | ||
return [4 /*yield*/, this.loginWithUser(user_1, infos)]; | ||
case 10: | ||
loginResult_1 = _a.sent(); | ||
this.hooks.emit(server_hooks_1.ServerHooks.LoginSuccess, hooksInfo); | ||
return [2 /*return*/, loginResult_1]; | ||
case 11: | ||
if (!this.services[serviceName]) { | ||
@@ -150,3 +216,3 @@ throw new accounts_error_1.AccountsJsError("No service with the name " + serviceName + " was registered.", errors_1.LoginWithServiceErrors.ServiceNotFound); | ||
return [4 /*yield*/, this.services[serviceName].authenticate(params)]; | ||
case 2: | ||
case 12: | ||
user = _a.sent(); | ||
@@ -160,17 +226,44 @@ hooksInfo.user = user; | ||
} | ||
return [4 /*yield*/, this.db.findUserAuthenticators(user.id)]; | ||
case 13: | ||
authenticators = _a.sent(); | ||
activeAuthenticator = authenticators.find(function (authenticator) { return authenticator.active; }); | ||
if (!activeAuthenticator) return [3 /*break*/, 15]; | ||
mfaChallengeToken = tokens_1.generateRandomToken(); | ||
// associate.id refer to the authenticator id | ||
return [4 /*yield*/, this.db.createMfaChallenge({ | ||
userId: user.id, | ||
token: mfaChallengeToken, | ||
})]; | ||
case 14: | ||
// associate.id refer to the authenticator id | ||
_a.sent(); | ||
return [2 /*return*/, { mfaToken: mfaChallengeToken }]; | ||
case 15: | ||
if (!this.options.enforceMfaForLogin) return [3 /*break*/, 17]; | ||
mfaChallengeToken = tokens_1.generateRandomToken(); | ||
return [4 /*yield*/, this.db.createMfaChallenge({ | ||
userId: user.id, | ||
token: mfaChallengeToken, | ||
scope: 'associate', | ||
})]; | ||
case 16: | ||
_a.sent(); | ||
return [2 /*return*/, { mfaToken: mfaChallengeToken }]; | ||
case 17: | ||
// Let the user validate the login attempt | ||
return [4 /*yield*/, this.hooks.emitSerial(server_hooks_1.ServerHooks.ValidateLogin, hooksInfo)]; | ||
case 18: | ||
// Let the user validate the login attempt | ||
return [4 /*yield*/, this.hooks.emitSerial(server_hooks_1.ServerHooks.ValidateLogin, hooksInfo)]; | ||
case 3: | ||
// Let the user validate the login attempt | ||
_a.sent(); | ||
return [4 /*yield*/, this.loginWithUser(user, infos)]; | ||
case 4: | ||
case 19: | ||
loginResult = _a.sent(); | ||
this.hooks.emit(server_hooks_1.ServerHooks.LoginSuccess, hooksInfo); | ||
return [2 /*return*/, loginResult]; | ||
case 5: | ||
case 20: | ||
err_2 = _a.sent(); | ||
this.hooks.emit(server_hooks_1.ServerHooks.LoginError, tslib_1.__assign(tslib_1.__assign({}, hooksInfo), { error: err_2 })); | ||
throw err_2; | ||
case 6: return [2 /*return*/]; | ||
case 21: return [2 /*return*/]; | ||
} | ||
@@ -580,2 +673,5 @@ }); | ||
}; | ||
/** | ||
* Private methods | ||
*/ | ||
AccountsServer.prototype.internalUserSanitizer = function (user) { | ||
@@ -582,0 +678,0 @@ return lodash_1.omit(user, ['services']); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ResumeSessionErrors = exports.FindSessionByAccessTokenErrors = exports.LogoutErrors = exports.RefreshTokensErrors = exports.ImpersonateErrors = exports.LoginWithServiceErrors = exports.AuthenticateWithServiceErrors = void 0; | ||
var AuthenticateWithServiceErrors; | ||
@@ -4,0 +5,0 @@ (function (AuthenticateWithServiceErrors) { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.AccountsServer = void 0; | ||
var accounts_server_1 = require("./accounts-server"); | ||
exports.AccountsServer = accounts_server_1.AccountsServer; | ||
Object.defineProperty(exports, "AccountsServer", { enumerable: true, get: function () { return accounts_server_1.AccountsServer; } }); | ||
var tokens_1 = require("./utils/tokens"); | ||
exports.generateRandomToken = tokens_1.generateRandomToken; | ||
Object.defineProperty(exports, "generateRandomToken", { enumerable: true, get: function () { return tokens_1.generateRandomToken; } }); | ||
var get_first_user_email_1 = require("./utils/get-first-user-email"); | ||
exports.getFirstUserEmail = get_first_user_email_1.getFirstUserEmail; | ||
Object.defineProperty(exports, "getFirstUserEmail", { enumerable: true, get: function () { return get_first_user_email_1.getFirstUserEmail; } }); | ||
var server_hooks_1 = require("./utils/server-hooks"); | ||
exports.ServerHooks = server_hooks_1.ServerHooks; | ||
Object.defineProperty(exports, "ServerHooks", { enumerable: true, get: function () { return server_hooks_1.ServerHooks; } }); | ||
var accounts_error_1 = require("./utils/accounts-error"); | ||
exports.AccountsJsError = accounts_error_1.AccountsJsError; | ||
Object.defineProperty(exports, "AccountsJsError", { enumerable: true, get: function () { return accounts_error_1.AccountsJsError; } }); | ||
var errors_1 = require("./errors"); | ||
exports.AuthenticateWithServiceErrors = errors_1.AuthenticateWithServiceErrors; | ||
exports.LoginWithServiceErrors = errors_1.LoginWithServiceErrors; | ||
exports.ImpersonateErrors = errors_1.ImpersonateErrors; | ||
exports.FindSessionByAccessTokenErrors = errors_1.FindSessionByAccessTokenErrors; | ||
exports.RefreshTokensErrors = errors_1.RefreshTokensErrors; | ||
exports.LogoutErrors = errors_1.LogoutErrors; | ||
exports.ResumeSessionErrors = errors_1.ResumeSessionErrors; | ||
Object.defineProperty(exports, "AuthenticateWithServiceErrors", { enumerable: true, get: function () { return errors_1.AuthenticateWithServiceErrors; } }); | ||
Object.defineProperty(exports, "LoginWithServiceErrors", { enumerable: true, get: function () { return errors_1.LoginWithServiceErrors; } }); | ||
Object.defineProperty(exports, "ImpersonateErrors", { enumerable: true, get: function () { return errors_1.ImpersonateErrors; } }); | ||
Object.defineProperty(exports, "FindSessionByAccessTokenErrors", { enumerable: true, get: function () { return errors_1.FindSessionByAccessTokenErrors; } }); | ||
Object.defineProperty(exports, "RefreshTokensErrors", { enumerable: true, get: function () { return errors_1.RefreshTokensErrors; } }); | ||
Object.defineProperty(exports, "LogoutErrors", { enumerable: true, get: function () { return errors_1.LogoutErrors; } }); | ||
Object.defineProperty(exports, "ResumeSessionErrors", { enumerable: true, get: function () { return errors_1.ResumeSessionErrors; } }); | ||
exports.default = accounts_server_1.AccountsServer; | ||
//# sourceMappingURL=index.js.map |
@@ -50,2 +50,7 @@ import * as jwt from 'jsonwebtoken'; | ||
useInternalUserObjectSanitizer?: boolean; | ||
/** | ||
* If set to true, the user will be asked to register a new MFA authenticator the first time | ||
* he tries to login. | ||
*/ | ||
enforceMfaForLogin?: boolean; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.AccountsJsError = void 0; | ||
var tslib_1 = require("tslib"); | ||
@@ -4,0 +5,0 @@ var AccountsJsError = /** @class */ (function (_super) { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.sendMail = exports.emailTemplates = void 0; | ||
var tslib_1 = require("tslib"); | ||
@@ -4,0 +5,0 @@ exports.emailTemplates = { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getFirstUserEmail = void 0; | ||
var lodash_1 = require("lodash"); | ||
@@ -4,0 +5,0 @@ function getFirstUserEmail(user, address) { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ServerHooks = void 0; | ||
exports.ServerHooks = { | ||
@@ -4,0 +5,0 @@ ValidateLogin: 'ValidateLogin', |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.generateRefreshToken = exports.generateAccessToken = exports.generateRandomToken = void 0; | ||
var tslib_1 = require("tslib"); | ||
@@ -4,0 +5,0 @@ var jwt = tslib_1.__importStar(require("jsonwebtoken")); |
{ | ||
"name": "@accounts/server", | ||
"version": "0.27.0", | ||
"version": "0.28.0-alpha.0", | ||
"description": "Fullstack authentication and accounts-management", | ||
@@ -43,3 +43,3 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"@accounts/types": "^0.27.0", | ||
"@accounts/types": "^0.28.0-alpha.0", | ||
"@types/jsonwebtoken": "8.3.9", | ||
@@ -50,3 +50,3 @@ "emittery": "0.5.1", | ||
"lodash": "4.17.15", | ||
"tslib": "1.11.2" | ||
"tslib": "2.0.0" | ||
}, | ||
@@ -56,7 +56,7 @@ "devDependencies": { | ||
"@types/jwt-decode": "2.2.1", | ||
"@types/node": "13.13.5", | ||
"@types/node": "14.0.13", | ||
"jest": "26.0.1", | ||
"rimraf": "3.0.2" | ||
}, | ||
"gitHead": "3f2f184f7d1f4229bfefb4ed99283de05a60d985" | ||
"gitHead": "9d3a051504a7c8a1698fd3c9cd8b1dbb11fcd906" | ||
} |
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
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
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
110007
63
1708
+ Added@accounts/types@0.28.0(transitive)
+ Addedtslib@2.0.0(transitive)
- Removed@accounts/types@0.27.0(transitive)
- Removedtslib@1.11.2(transitive)
Updatedtslib@2.0.0