@spinajs/rbac-http 2.0.28 → 2.0.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/lib/2fa/SpeakEasy2FaToken.d.ts +13 -0
  2. package/lib/2fa/SpeakEasy2FaToken.js +91 -0
  3. package/lib/2fa/SpeakEasy2FaToken.js.map +1 -0
  4. package/lib/config/rbac-http.js +19 -0
  5. package/lib/config/rbac-http.js.map +1 -1
  6. package/lib/controllers/LoginController.d.ts +26 -4
  7. package/lib/controllers/LoginController.js +240 -24
  8. package/lib/controllers/LoginController.js.map +1 -1
  9. package/lib/controllers/TwoFactorAuthController.d.ts +11 -0
  10. package/lib/controllers/TwoFactorAuthController.js +71 -0
  11. package/lib/controllers/TwoFactorAuthController.js.map +1 -0
  12. package/lib/controllers/UserController.d.ts +1 -1
  13. package/lib/controllers/UserController.js +7 -11
  14. package/lib/controllers/UserController.js.map +1 -1
  15. package/lib/controllers/UserMetadata.js +4 -0
  16. package/lib/controllers/UserMetadata.js.map +1 -1
  17. package/lib/decorators.js +6 -10
  18. package/lib/decorators.js.map +1 -1
  19. package/lib/dto/login-dto.d.ts +1 -6
  20. package/lib/dto/login-dto.js +7 -8
  21. package/lib/dto/login-dto.js.map +1 -1
  22. package/lib/dto/restore-password-dto.d.ts +23 -0
  23. package/lib/dto/restore-password-dto.js +34 -0
  24. package/lib/dto/restore-password-dto.js.map +1 -0
  25. package/lib/dto/token-dto.d.ts +15 -0
  26. package/lib/dto/token-dto.js +32 -0
  27. package/lib/dto/token-dto.js.map +1 -0
  28. package/lib/dto/userLogin-dto.d.ts +21 -0
  29. package/lib/dto/userLogin-dto.js +34 -0
  30. package/lib/dto/userLogin-dto.js.map +1 -0
  31. package/lib/events/UserLoginFailed.d.ts +5 -0
  32. package/lib/events/UserLoginFailed.js +25 -0
  33. package/lib/events/UserLoginFailed.js.map +1 -0
  34. package/lib/events/UserLoginSuccess.d.ts +5 -0
  35. package/lib/events/UserLoginSuccess.js +25 -0
  36. package/lib/events/UserLoginSuccess.js.map +1 -0
  37. package/lib/events/UserPassordRestore.d.ts +6 -0
  38. package/lib/events/UserPassordRestore.js +26 -0
  39. package/lib/events/UserPassordRestore.js.map +1 -0
  40. package/lib/fingerprint/FingerprintJs.d.ts +3 -0
  41. package/lib/fingerprint/FingerprintJs.js +18 -0
  42. package/lib/fingerprint/FingerprintJs.js.map +1 -0
  43. package/lib/index.d.ts +1 -1
  44. package/lib/index.js +1 -1
  45. package/lib/index.js.map +1 -1
  46. package/lib/interfaces.d.ts +35 -0
  47. package/lib/interfaces.js +7 -0
  48. package/lib/interfaces.js.map +1 -1
  49. package/lib/middlewares/AttributeFilter.d.ts +10 -0
  50. package/lib/middlewares/AttributeFilter.js +19 -0
  51. package/lib/middlewares/AttributeFilter.js.map +1 -0
  52. package/lib/middlewares.d.ts +1 -1
  53. package/lib/middlewares.js +1 -1
  54. package/lib/middlewares.js.map +1 -1
  55. package/lib/policies/2FaPolicy.d.ts +7 -0
  56. package/lib/policies/2FaPolicy.js +32 -0
  57. package/lib/policies/2FaPolicy.js.map +1 -0
  58. package/lib/policies/AuthPolicy.d.ts +9 -0
  59. package/lib/policies/AuthPolicy.js +23 -0
  60. package/lib/policies/AuthPolicy.js.map +1 -0
  61. package/lib/policies/LoggedPolicy.d.ts +9 -0
  62. package/lib/policies/LoggedPolicy.js +23 -0
  63. package/lib/policies/LoggedPolicy.js.map +1 -0
  64. package/lib/policies/NotLoggedPolicy.d.ts +9 -0
  65. package/lib/policies/NotLoggedPolicy.js +22 -0
  66. package/lib/policies/NotLoggedPolicy.js.map +1 -0
  67. package/lib/policies/RbacPolicy.d.ts +15 -0
  68. package/lib/policies/RbacPolicy.js +60 -0
  69. package/lib/policies/RbacPolicy.js.map +1 -0
  70. package/lib/policies/captchaPolicy.d.ts +0 -0
  71. package/lib/policies/captchaPolicy.js +1 -0
  72. package/lib/policies/captchaPolicy.js.map +1 -0
  73. package/package.json +19 -13
@@ -0,0 +1,13 @@
1
+ import { TwoFactorAuthProvider } from '../interfaces';
2
+ import { User } from '@spinajs/rbac';
3
+ import { Log } from '@spinajs/log';
4
+ export declare class SpeakEasy2FaToken extends TwoFactorAuthProvider {
5
+ protected Config: any;
6
+ protected Log: Log;
7
+ constructor();
8
+ execute(_: User): Promise<void>;
9
+ verifyToken(token: string, user: User): Promise<boolean>;
10
+ initialize(user: User): Promise<any>;
11
+ isEnabled(user: User): Promise<boolean>;
12
+ isInitialized(user: User): Promise<boolean>;
13
+ }
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
23
+ };
24
+ var __importStar = (this && this.__importStar) || function (mod) {
25
+ if (mod && mod.__esModule) return mod;
26
+ var result = {};
27
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
28
+ __setModuleDefault(result, mod);
29
+ return result;
30
+ };
31
+ var __metadata = (this && this.__metadata) || function (k, v) {
32
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.SpeakEasy2FaToken = void 0;
36
+ const di_1 = require("@spinajs/di");
37
+ const interfaces_1 = require("../interfaces");
38
+ const speakeasy = __importStar(require("speakeasy"));
39
+ const configuration_1 = require("@spinajs/configuration");
40
+ const log_1 = require("@spinajs/log");
41
+ let SpeakEasy2FaToken = class SpeakEasy2FaToken extends interfaces_1.TwoFactorAuthProvider {
42
+ constructor() {
43
+ super();
44
+ }
45
+ execute(_) {
46
+ // empty, speakasy works offline eg. google authenticator
47
+ // we dont send any email or sms
48
+ return Promise.resolve();
49
+ }
50
+ async verifyToken(token, user) {
51
+ const meta = user.Metadata.find((x) => x.Key === '2fa_speakeasy_token');
52
+ if (!meta || meta.Value === '') {
53
+ this.Log.trace(`Cannot verify 2fa token, no 2fa token for user ${user.Id}`);
54
+ return false;
55
+ }
56
+ const verified = speakeasy.totp.verify({
57
+ secret: meta.Value,
58
+ encoding: 'base32',
59
+ token,
60
+ window: 5,
61
+ });
62
+ return verified;
63
+ }
64
+ async initialize(user) {
65
+ const secret = speakeasy.generateSecret(this.Config);
66
+ await (user.Metadata['2fa_speakeasy_token'] = secret.base32);
67
+ return secret.base32;
68
+ }
69
+ async isEnabled(user) {
70
+ const val = await user.Metadata['2fa_enabled'];
71
+ return val;
72
+ }
73
+ async isInitialized(user) {
74
+ const val = await user.Metadata['2fa_speakeasy_token'];
75
+ return val !== '';
76
+ }
77
+ };
78
+ __decorate([
79
+ (0, configuration_1.Config)('rbac.speakeasy'),
80
+ __metadata("design:type", Object)
81
+ ], SpeakEasy2FaToken.prototype, "Config", void 0);
82
+ __decorate([
83
+ (0, log_1.Logger)('SPEAKEASY_2FA_TOKEN'),
84
+ __metadata("design:type", log_1.Log)
85
+ ], SpeakEasy2FaToken.prototype, "Log", void 0);
86
+ SpeakEasy2FaToken = __decorate([
87
+ (0, di_1.Injectable)(interfaces_1.TwoFactorAuthProvider),
88
+ __metadata("design:paramtypes", [])
89
+ ], SpeakEasy2FaToken);
90
+ exports.SpeakEasy2FaToken = SpeakEasy2FaToken;
91
+ //# sourceMappingURL=SpeakEasy2FaToken.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SpeakEasy2FaToken.js","sourceRoot":"","sources":["../../src/2fa/SpeakEasy2FaToken.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,oCAAyC;AACzC,8CAAsD;AACtD,qDAAuC;AAEvC,0DAAgD;AAChD,sCAA2C;AAG3C,IAAa,iBAAiB,GAA9B,MAAa,iBAAkB,SAAQ,kCAAqB;IAO1D;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAEM,OAAO,CAAC,CAAO;QACpB,yDAAyD;QACzD,gCAAgC;QAChC,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,KAAa,EAAE,IAAU;QAChD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,qBAAqB,CAAC,CAAC;QAExE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,EAAE,EAAE;YAC9B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,kDAAkD,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YAE5E,OAAO,KAAK,CAAC;SACd;QAED,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;YACrC,MAAM,EAAE,IAAI,CAAC,KAAK;YAClB,QAAQ,EAAE,QAAQ;YAClB,KAAK;YACL,MAAM,EAAE,CAAC;SACV,CAAC,CAAC;QAEH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,IAAU;QAChC,MAAM,MAAM,GAAG,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC7D,OAAO,MAAM,CAAC,MAAM,CAAC;IACvB,CAAC;IAEM,KAAK,CAAC,SAAS,CAAC,IAAU;QAC/B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAC/C,OAAO,GAAc,CAAC;IACxB,CAAC;IAEM,KAAK,CAAC,aAAa,CAAC,IAAU;QACnC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC;QACvD,OAAO,GAAG,KAAK,EAAE,CAAC;IACpB,CAAC;CACF,CAAA;AAjDC;IADC,IAAA,sBAAM,EAAC,gBAAgB,CAAC;;iDACH;AAGtB;IADC,IAAA,YAAM,EAAC,qBAAqB,CAAC;8BACf,SAAG;8CAAC;AALR,iBAAiB;IAD7B,IAAA,eAAU,EAAC,kCAAqB,CAAC;;GACrB,iBAAiB,CAmD7B;AAnDY,8CAAiB"}
@@ -12,6 +12,25 @@ module.exports = {
12
12
  views: [dir('./../views')],
13
13
  },
14
14
  },
15
+ rbac: {
16
+ twoFactorAuth: {
17
+ enabled: true,
18
+ service: 'SpeakEasy2FaToken',
19
+ },
20
+ fingerprint: {
21
+ enabled: false,
22
+ maxDevices: 3,
23
+ service: 'FingerprintJs',
24
+ },
25
+ password: {
26
+ // password reset token ttl in minutes
27
+ tokenTTL: 60,
28
+ /**
29
+ * Block account after invalid login attempts
30
+ */
31
+ blockAfterAttempts: 3,
32
+ },
33
+ },
15
34
  http: {
16
35
  middlewares: [
17
36
  // add global user from session middleware
@@ -1 +1 @@
1
- {"version":3,"file":"rbac-http.js","sourceRoot":"","sources":["../../src/config/rbac-http.ts"],"names":[],"mappings":";;AAAA,+BAAgD;AAEhD,SAAS,GAAG,CAAC,IAAY;IACvB,OAAO,IAAA,cAAO,EAAC,IAAA,gBAAS,EAAC,IAAA,WAAI,EAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC;AACD,MAAM,CAAC,OAAO,GAAG;IACf,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,WAAW,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;YACtC,OAAO,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAC9B,KAAK,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;SAC3B;KACF;IACD,IAAI,EAAE;QACJ,WAAW,EAAE;QACX,0CAA0C;SAC3C;KACF;CACF,CAAC"}
1
+ {"version":3,"file":"rbac-http.js","sourceRoot":"","sources":["../../src/config/rbac-http.ts"],"names":[],"mappings":";;AAAA,+BAAgD;AAEhD,SAAS,GAAG,CAAC,IAAY;IACvB,OAAO,IAAA,cAAO,EAAC,IAAA,gBAAS,EAAC,IAAA,WAAI,EAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC;AACD,MAAM,CAAC,OAAO,GAAG;IACf,MAAM,EAAE;QACN,IAAI,EAAE;YACJ,WAAW,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;YACtC,OAAO,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAC9B,KAAK,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;SAC3B;KACF;IACD,IAAI,EAAE;QACJ,aAAa,EAAE;YACb,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,mBAAmB;SAC7B;QACD,WAAW,EAAE;YACX,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,CAAC;YACb,OAAO,EAAE,eAAe;SACzB;QACD,QAAQ,EAAE;YACR,sCAAsC;YACtC,QAAQ,EAAE,EAAE;YAEZ;;eAEG;YACH,kBAAkB,EAAE,CAAC;SACtB;KACF;IACD,IAAI,EAAE;QACJ,WAAW,EAAE;QACX,0CAA0C;SAC3C;KACF;CACF,CAAC"}
@@ -1,12 +1,34 @@
1
- import { LoginDto } from './../dto/login-dto';
2
- import { BaseController, Ok, CookieResponse, Unauthorized, NotAllowed } from '@spinajs/http';
3
- import { AuthProvider, SessionProvider, User as UserModel } from '@spinajs/rbac';
1
+ import { InvalidOperation } from '@spinajs/exceptions';
2
+ import { UserLoginDto } from '../dto/userLogin-dto';
3
+ import { BaseController, Ok, CookieResponse, Unauthorized, BadRequest, NotFound } from '@spinajs/http';
4
+ import { AuthProvider, FederatedAuthProvider, PasswordProvider, PasswordValidationProvider, SessionProvider, User as UserModel } from '@spinajs/rbac';
4
5
  import { Configuration } from '@spinajs/configuration';
6
+ import { FingerprintProvider, TwoFactorAuthProvider } from '../interfaces';
7
+ import { QueueClient } from '@spinajs/queue';
8
+ import { RestorePasswordDto } from '../dto/restore-password-dto';
5
9
  export declare class LoginController extends BaseController {
6
10
  protected Configuration: Configuration;
7
11
  protected AuthProvider: AuthProvider;
8
12
  protected SessionProvider: SessionProvider;
9
13
  protected SessionExpirationTime: number;
10
- login(credentials: LoginDto, logged: UserModel): Promise<Unauthorized | CookieResponse | NotAllowed>;
14
+ protected PasswordResetTokenTTL: number;
15
+ protected TwoFactorAuthProvider: TwoFactorAuthProvider;
16
+ protected FingerprintProvider: FingerprintProvider;
17
+ protected PasswordValidationService: PasswordValidationProvider;
18
+ protected FederatedLoginStrategies: FederatedAuthProvider<any>[];
19
+ protected PasswordProvider: PasswordProvider;
20
+ protected Queue: QueueClient;
21
+ loginFederated(credentials: unknown, caller: string): Promise<Unauthorized | CookieResponse>;
22
+ /**
23
+ *
24
+ * Api call for listing avaible federated login strategies
25
+ *
26
+ * @returns response with avaible login strategies
27
+ */
28
+ federatedLoginList(): Promise<Ok>;
29
+ login(credentials: UserLoginDto): Promise<Unauthorized | CookieResponse>;
30
+ setNewPassword(token: string, pwd: RestorePasswordDto): Promise<BadRequest | NotFound>;
31
+ forgotPassword(login: UserLoginDto): Promise<InvalidOperation | Ok>;
11
32
  logout(ssid: string): Promise<Ok | CookieResponse>;
33
+ protected authenticate(user: UserModel, federated?: boolean): Promise<Unauthorized | CookieResponse>;
12
34
  }
@@ -11,38 +11,133 @@ var __metadata = (this && this.__metadata) || function (k, v) {
11
11
  var __param = (this && this.__param) || function (paramIndex, decorator) {
12
12
  return function (target, key) { decorator(target, key, paramIndex); }
13
13
  };
14
- var __importDefault = (this && this.__importDefault) || function (mod) {
15
- return (mod && mod.__esModule) ? mod : { "default": mod };
16
- };
17
14
  Object.defineProperty(exports, "__esModule", { value: true });
18
15
  exports.LoginController = void 0;
19
- const login_dto_1 = require("./../dto/login-dto");
16
+ const exceptions_1 = require("@spinajs/exceptions");
17
+ const userLogin_dto_1 = require("../dto/userLogin-dto");
20
18
  const http_1 = require("@spinajs/http");
21
19
  const rbac_1 = require("@spinajs/rbac");
22
20
  const di_1 = require("@spinajs/di");
23
21
  const configuration_1 = require("@spinajs/configuration");
24
- const decorators_1 = require("./../decorators");
25
- const lodash_1 = __importDefault(require("lodash"));
22
+ const interfaces_1 = require("../interfaces");
23
+ const queue_1 = require("@spinajs/queue");
24
+ const NotLoggedPolicy_1 = require("../policies/NotLoggedPolicy");
25
+ const LoggedPolicy_1 = require("../policies/LoggedPolicy");
26
+ const UserPassordRestore_1 = require("../events/UserPassordRestore");
27
+ const restore_password_dto_1 = require("../dto/restore-password-dto");
28
+ const uuid_1 = require("uuid");
29
+ const luxon_1 = require("luxon");
30
+ const rbac_2 = require("@spinajs/rbac");
31
+ const UserLoginSuccess_1 = require("../events/UserLoginSuccess");
26
32
  let LoginController = class LoginController extends http_1.BaseController {
27
- async login(credentials, logged) {
28
- if (logged) {
29
- return new http_1.NotAllowed('User already logged in. Please logout before trying to authorize.');
33
+ async loginFederated(credentials, caller) {
34
+ const strategy = this.FederatedLoginStrategies.find((x) => x.callerCheck(caller));
35
+ if (!strategy) {
36
+ throw new exceptions_1.InvalidOperation(`No auth stragegy registered for caller ${caller}`);
37
+ }
38
+ const result = await strategy.authenticate(credentials);
39
+ if (!result.Error) {
40
+ // proceed with standard authentication
41
+ return await this.authenticate(result.User);
42
+ }
43
+ return new http_1.Unauthorized(result.Error);
44
+ }
45
+ /**
46
+ *
47
+ * Api call for listing avaible federated login strategies
48
+ *
49
+ * @returns response with avaible login strategies
50
+ */
51
+ async federatedLoginList() {
52
+ return new http_1.Ok(this.FederatedLoginStrategies.map((x) => x.Name));
53
+ }
54
+ async login(credentials) {
55
+ const result = await this.AuthProvider.authenticate(credentials.Email, credentials.Password);
56
+ if (!result.Error) {
57
+ // proceed with standard authentication
58
+ return await this.authenticate(result.User);
30
59
  }
31
- const user = await this.AuthProvider.authenticate(credentials.Email, credentials.Password);
60
+ return new http_1.Unauthorized(result.Error);
61
+ }
62
+ async setNewPassword(token, pwd) {
63
+ const user = await rbac_1.User.query()
64
+ .innerJoin(rbac_1.UserMetadata, function () {
65
+ this.where({
66
+ Key: 'password:reset:token',
67
+ Value: token,
68
+ });
69
+ })
70
+ .populate('Metadata')
71
+ .first();
32
72
  if (!user) {
33
- return new http_1.Unauthorized({
73
+ return new http_1.NotFound({
34
74
  error: {
35
- message: 'login or password incorrect',
75
+ code: 'ERR_USER_NOT_FOUND',
76
+ message: 'No user found for this reset token',
36
77
  },
37
78
  });
38
79
  }
39
- await user.Metadata.populate();
40
- const session = new rbac_1.Session();
41
- const sData = user.dehydrate();
42
- session.Data.set('User', sData);
43
- await this.SessionProvider.save(session);
44
- // BEWARE: httpOnly coockie, only accesible via http method in browser
45
- return new http_1.CookieResponse('ssid', session.SessionId, this.SessionExpirationTime, true, lodash_1.default.omit(sData, ['Id']), { httpOnly: true });
80
+ const val = (await user.Metadata['password:reset:start']);
81
+ const now = luxon_1.DateTime.now().plus({ seconds: -this.PasswordResetTokenTTL });
82
+ if (val < now) {
83
+ return new http_1.BadRequest({
84
+ error: {
85
+ code: 'ERR_RESET_TOKEN_EXPIRED',
86
+ message: 'Password reset token expired',
87
+ },
88
+ });
89
+ }
90
+ if (!this.PasswordValidationService.check(pwd.Password)) {
91
+ return new http_1.BadRequest({
92
+ error: {
93
+ code: 'ERR_PASSWORD_RULE',
94
+ message: 'Invalid password, does not match password rules',
95
+ },
96
+ });
97
+ }
98
+ if (pwd.Password !== pwd.ConfirmPassword) {
99
+ return new http_1.BadRequest({
100
+ error: {
101
+ code: 'ERR_PASSWORD_NOT_MATCH',
102
+ message: 'Password and repeat password does not match',
103
+ },
104
+ });
105
+ }
106
+ const hashedPassword = await this.PasswordProvider.hash(pwd.Password);
107
+ user.Password = hashedPassword;
108
+ await user.update();
109
+ /**
110
+ * Delete all reset related meta for user
111
+ */
112
+ await user.Metadata.delete(/password:reset.*/);
113
+ // add to action list
114
+ await user.Actions.add(new rbac_2.UserAction({
115
+ Persistent: true,
116
+ Action: 'password:reset',
117
+ }));
118
+ // inform others
119
+ await this.Queue.emit(new rbac_1.UserPasswordChanged(user.Uuid));
120
+ }
121
+ async forgotPassword(login) {
122
+ const user = await this.AuthProvider.getByEmail(login.Email);
123
+ if (!user.IsActive || user.IsBanned || user.DeletedAt !== null) {
124
+ return new exceptions_1.InvalidOperation('User is inactive, banned or deleted. Contact system administrator');
125
+ }
126
+ const token = (0, uuid_1.v4)();
127
+ // assign meta to user
128
+ await (user.Metadata['password:reset'] = true);
129
+ await (user.Metadata['password:reset:token'] = token);
130
+ await (user.Metadata['password:reset:start'] = luxon_1.DateTime.now());
131
+ await user.Actions.add(new rbac_2.UserAction({
132
+ Action: 'user:password:reset',
133
+ Data: luxon_1.DateTime.now().toISO(),
134
+ Persistent: true,
135
+ }));
136
+ await this.Queue.emit(new UserPassordRestore_1.UserPasswordRestore(user.Uuid, token));
137
+ return new http_1.Ok({
138
+ reset_token: token,
139
+ ttl: this.PasswordResetTokenTTL,
140
+ });
46
141
  }
47
142
  async logout(ssid) {
48
143
  if (!ssid) {
@@ -52,33 +147,154 @@ let LoginController = class LoginController extends http_1.BaseController {
52
147
  // send empty cookie to confirm session deletion
53
148
  return new http_1.CookieResponse('ssid', null, this.SessionExpirationTime);
54
149
  }
150
+ async authenticate(user, federated) {
151
+ if (!user) {
152
+ return new http_1.Unauthorized({
153
+ error: {
154
+ message: 'login or password incorrect',
155
+ },
156
+ });
157
+ }
158
+ await user.Metadata.populate();
159
+ const session = new rbac_1.Session();
160
+ const dUser = user.dehydrate();
161
+ session.Data.set('User', dUser);
162
+ // we found user but we still dont know if is authorized
163
+ // eg. 2fa auth is not performed
164
+ // create session, but user is not yet authorized
165
+ session.Data.set('Authorized', false);
166
+ // if its federated login, skip 2fa - assume
167
+ // external login service provided it
168
+ if (this.TwoFactorConfig.enabled || !federated) {
169
+ await this.SessionProvider.save(session);
170
+ const enabledForUser = await this.TwoFactorAuthProvider.isEnabled(user);
171
+ /**
172
+ * if 2fa is enabled for user, proceed
173
+ */
174
+ if (enabledForUser) {
175
+ /**
176
+ * check if 2fa system is initialized for user eg. private key is generated.
177
+ */
178
+ const isInitialized = await this.TwoFactorAuthProvider.isInitialized(user);
179
+ if (!isInitialized) {
180
+ const twoFaResult = await this.TwoFactorAuthProvider.initialize(user);
181
+ return new http_1.CookieResponse('ssid', session.SessionId, this.SessionExpirationTime, true, {
182
+ toFactorAuth: true,
183
+ twoFactorAuthFirstTime: true,
184
+ method: this.TwoFactorConfig.service,
185
+ data: twoFaResult,
186
+ }, { httpOnly: true });
187
+ }
188
+ // give chance to execute 2fa eg. send sms or email
189
+ await this.TwoFactorAuthProvider.execute(user);
190
+ // return session to identify user
191
+ // and only info that twoFactor auth is requested
192
+ return new http_1.CookieResponse('ssid', session.SessionId, this.SessionExpirationTime, true, {
193
+ toFactorAuth: true,
194
+ }, { httpOnly: true });
195
+ }
196
+ }
197
+ // 2fa is not enabled, so we found user, it means it is logged
198
+ session.Data.set('Authorized', true);
199
+ await this.SessionProvider.save(session);
200
+ await this.Queue.emit(new UserLoginSuccess_1.UserLoginSuccess(user.Uuid));
201
+ user.LastLoginAt = luxon_1.DateTime.now();
202
+ await user.update();
203
+ // BEWARE: httpOnly coockie, only accesible via http method in browser
204
+ // return coockie session id with additional user data
205
+ return new http_1.CookieResponse('ssid', session.SessionId, this.SessionExpirationTime, true, dUser, { httpOnly: true });
206
+ }
55
207
  };
56
208
  __decorate([
57
209
  (0, di_1.Autoinject)(),
58
210
  __metadata("design:type", configuration_1.Configuration)
59
211
  ], LoginController.prototype, "Configuration", void 0);
60
212
  __decorate([
61
- (0, di_1.Autoinject)(),
213
+ (0, configuration_1.AutoinjectService)('rbac.auth'),
62
214
  __metadata("design:type", rbac_1.AuthProvider)
63
215
  ], LoginController.prototype, "AuthProvider", void 0);
64
216
  __decorate([
65
- (0, di_1.Autoinject)(),
217
+ (0, configuration_1.AutoinjectService)('rbac.session'),
66
218
  __metadata("design:type", rbac_1.SessionProvider)
67
219
  ], LoginController.prototype, "SessionProvider", void 0);
68
220
  __decorate([
69
- (0, configuration_1.Config)('rbac.session.expiration', 120),
221
+ (0, configuration_1.Config)('rbac.session.expiration', {
222
+ defaultValue: 120,
223
+ }),
70
224
  __metadata("design:type", Number)
71
225
  ], LoginController.prototype, "SessionExpirationTime", void 0);
226
+ __decorate([
227
+ (0, configuration_1.Config)('rbac.password_reset.ttl'),
228
+ __metadata("design:type", Number)
229
+ ], LoginController.prototype, "PasswordResetTokenTTL", void 0);
230
+ __decorate([
231
+ (0, configuration_1.AutoinjectService)('rbac.twoFactorAuth'),
232
+ __metadata("design:type", interfaces_1.TwoFactorAuthProvider)
233
+ ], LoginController.prototype, "TwoFactorAuthProvider", void 0);
234
+ __decorate([
235
+ (0, configuration_1.AutoinjectService)('rbac.fingerprint.provider'),
236
+ __metadata("design:type", interfaces_1.FingerprintProvider)
237
+ ], LoginController.prototype, "FingerprintProvider", void 0);
238
+ __decorate([
239
+ (0, configuration_1.AutoinjectService)('rbac.password.validation'),
240
+ __metadata("design:type", rbac_1.PasswordValidationProvider)
241
+ ], LoginController.prototype, "PasswordValidationService", void 0);
242
+ __decorate([
243
+ (0, di_1.Autoinject)(rbac_1.FederatedAuthProvider),
244
+ __metadata("design:type", Array)
245
+ ], LoginController.prototype, "FederatedLoginStrategies", void 0);
246
+ __decorate([
247
+ (0, di_1.Autoinject)(),
248
+ __metadata("design:type", rbac_1.PasswordProvider)
249
+ ], LoginController.prototype, "PasswordProvider", void 0);
250
+ __decorate([
251
+ (0, di_1.Autoinject)(queue_1.QueueClient),
252
+ __metadata("design:type", queue_1.QueueClient)
253
+ ], LoginController.prototype, "Queue", void 0);
254
+ __decorate([
255
+ (0, http_1.Post)('federated-login'),
256
+ (0, http_1.Policy)(NotLoggedPolicy_1.NotLoggedPolicy),
257
+ __param(0, (0, http_1.Body)()),
258
+ __param(1, (0, http_1.Header)('Host')),
259
+ __metadata("design:type", Function),
260
+ __metadata("design:paramtypes", [Object, String]),
261
+ __metadata("design:returntype", Promise)
262
+ ], LoginController.prototype, "loginFederated", null);
263
+ __decorate([
264
+ (0, http_1.Get)(),
265
+ (0, http_1.Policy)(NotLoggedPolicy_1.NotLoggedPolicy),
266
+ __metadata("design:type", Function),
267
+ __metadata("design:paramtypes", []),
268
+ __metadata("design:returntype", Promise)
269
+ ], LoginController.prototype, "federatedLoginList", null);
72
270
  __decorate([
73
271
  (0, http_1.Post)(),
272
+ (0, http_1.Policy)(NotLoggedPolicy_1.NotLoggedPolicy),
74
273
  __param(0, (0, http_1.Body)()),
75
- __param(1, (0, decorators_1.User)()),
76
274
  __metadata("design:type", Function),
77
- __metadata("design:paramtypes", [login_dto_1.LoginDto, rbac_1.User]),
275
+ __metadata("design:paramtypes", [userLogin_dto_1.UserLoginDto]),
78
276
  __metadata("design:returntype", Promise)
79
277
  ], LoginController.prototype, "login", null);
278
+ __decorate([
279
+ (0, http_1.Post)('new-password'),
280
+ (0, http_1.Policy)(NotLoggedPolicy_1.NotLoggedPolicy),
281
+ __param(0, (0, http_1.Query)()),
282
+ __param(1, (0, http_1.Body)()),
283
+ __metadata("design:type", Function),
284
+ __metadata("design:paramtypes", [String, restore_password_dto_1.RestorePasswordDto]),
285
+ __metadata("design:returntype", Promise)
286
+ ], LoginController.prototype, "setNewPassword", null);
287
+ __decorate([
288
+ (0, http_1.Post)('forgot-password'),
289
+ (0, http_1.Policy)(NotLoggedPolicy_1.NotLoggedPolicy),
290
+ __param(0, (0, http_1.Body)()),
291
+ __metadata("design:type", Function),
292
+ __metadata("design:paramtypes", [userLogin_dto_1.UserLoginDto]),
293
+ __metadata("design:returntype", Promise)
294
+ ], LoginController.prototype, "forgotPassword", null);
80
295
  __decorate([
81
296
  (0, http_1.Get)(),
297
+ (0, http_1.Policy)(LoggedPolicy_1.LoggedPolicy),
82
298
  __param(0, (0, http_1.Cookie)()),
83
299
  __metadata("design:type", Function),
84
300
  __metadata("design:paramtypes", [String]),
@@ -1 +1 @@
1
- {"version":3,"file":"LoginController.js","sourceRoot":"","sources":["../../src/controllers/LoginController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,kDAA8C;AAC9C,wCAAgI;AAChI,wCAA0F;AAC1F,oCAAyC;AACzC,0DAA+D;AAC/D,gDAAuC;AACvC,oDAAuB;AAGvB,IAAa,eAAe,GAA5B,MAAa,eAAgB,SAAQ,qBAAc;IAc1C,KAAK,CAAC,KAAK,CAAS,WAAqB,EAAU,MAAiB;QACzE,IAAI,MAAM,EAAE;YACV,OAAO,IAAI,iBAAU,CAAC,mEAAmE,CAAC,CAAC;SAC5F;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;QAE3F,IAAI,CAAC,IAAI,EAAE;YACT,OAAO,IAAI,mBAAY,CAAC;gBACtB,KAAK,EAAE;oBACL,OAAO,EAAE,6BAA6B;iBACvC;aACF,CAAC,CAAC;SACJ;QAED,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAE/B,MAAM,OAAO,GAAG,IAAI,cAAO,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAE/B,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAEhC,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAEzC,sEAAsE;QACtE,OAAO,IAAI,qBAAc,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,qBAAqB,EAAE,IAAI,EAAE,gBAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACpI,CAAC;IAGM,KAAK,CAAC,MAAM,CAAW,IAAY;QACxC,IAAI,CAAC,IAAI,EAAE;YACT,OAAO,IAAI,SAAE,EAAE,CAAC;SACjB;QAED,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAExC,gDAAgD;QAChD,OAAO,IAAI,qBAAc,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACtE,CAAC;CACF,CAAA;AAnDC;IADC,IAAA,eAAU,GAAE;8BACY,6BAAa;sDAAC;AAGvC;IADC,IAAA,eAAU,GAAE;8BACW,mBAAY;qDAAC;AAGrC;IADC,IAAA,eAAU,GAAE;8BACc,sBAAe;wDAAC;AAG3C;IADC,IAAA,sBAAM,EAAC,yBAAyB,EAAE,GAAG,CAAC;;8DACC;AAGxC;IADC,IAAA,WAAI,GAAE;IACa,WAAA,IAAA,WAAI,GAAE,CAAA;IAAyB,WAAA,IAAA,iBAAI,GAAE,CAAA;;qCAAjB,oBAAQ,EAAkB,WAAS;;4CA0B1E;AAGD;IADC,IAAA,UAAG,GAAE;IACe,WAAA,IAAA,aAAM,GAAE,CAAA;;;;6CAS5B;AApDU,eAAe;IAD3B,IAAA,eAAQ,EAAC,WAAW,CAAC;GACT,eAAe,CAqD3B;AArDY,0CAAe"}
1
+ {"version":3,"file":"LoginController.js","sourceRoot":"","sources":["../../src/controllers/LoginController.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { TokenDto } from './../dto/token-dto';
2
+ import { BaseController, Ok, Unauthorized } from '@spinajs/http';
3
+ import { SessionProvider, User as UserModel } from '@spinajs/rbac';
4
+ import { TwoFactorAuthProvider } from '../interfaces';
5
+ import { QueueClient } from '@spinajs/queue';
6
+ export declare class TwoFactorAuthController extends BaseController {
7
+ protected Queue: QueueClient;
8
+ protected SessionProvider: SessionProvider;
9
+ protected TwoFactorAuthProvider: TwoFactorAuthProvider;
10
+ verifyToken(logged: UserModel, token: TokenDto, ssid: string): Promise<Ok | Unauthorized>;
11
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.TwoFactorAuthController = void 0;
16
+ const token_dto_1 = require("./../dto/token-dto");
17
+ const http_1 = require("@spinajs/http");
18
+ const rbac_1 = require("@spinajs/rbac");
19
+ const http_2 = require("@spinajs/http");
20
+ const decorators_1 = require("../decorators");
21
+ const _2FaPolicy_1 = require("../policies/2FaPolicy");
22
+ const configuration_1 = require("@spinajs/configuration");
23
+ const interfaces_1 = require("../interfaces");
24
+ const luxon_1 = require("luxon");
25
+ const UserLoginSuccess_1 = require("../events/UserLoginSuccess");
26
+ const di_1 = require("@spinajs/di");
27
+ const queue_1 = require("@spinajs/queue");
28
+ let TwoFactorAuthController = class TwoFactorAuthController extends http_1.BaseController {
29
+ async verifyToken(logged, token, ssid) {
30
+ const result = await this.TwoFactorAuthProvider.verifyToken(token.Token, logged);
31
+ if (result) {
32
+ return new http_1.Unauthorized(`invalid token`);
33
+ }
34
+ logged.LastLoginAt = luxon_1.DateTime.now();
35
+ await logged.update();
36
+ await this.Queue.emit(new UserLoginSuccess_1.UserLoginSuccess(logged.Uuid));
37
+ await this.SessionProvider.save(ssid, {
38
+ Authorized: true,
39
+ TwoFactorAuth_check: true,
40
+ });
41
+ // return user data
42
+ return new http_1.Ok(logged.dehydrate());
43
+ }
44
+ };
45
+ __decorate([
46
+ (0, di_1.Autoinject)(queue_1.QueueClient),
47
+ __metadata("design:type", queue_1.QueueClient)
48
+ ], TwoFactorAuthController.prototype, "Queue", void 0);
49
+ __decorate([
50
+ (0, configuration_1.AutoinjectService)('rbac.session'),
51
+ __metadata("design:type", rbac_1.SessionProvider)
52
+ ], TwoFactorAuthController.prototype, "SessionProvider", void 0);
53
+ __decorate([
54
+ (0, configuration_1.AutoinjectService)('rbac.twoFactorAuth'),
55
+ __metadata("design:type", interfaces_1.TwoFactorAuthProvider)
56
+ ], TwoFactorAuthController.prototype, "TwoFactorAuthProvider", void 0);
57
+ __decorate([
58
+ (0, http_1.Post)('2fa/verify'),
59
+ __param(0, (0, decorators_1.User)()),
60
+ __param(1, (0, http_2.Body)()),
61
+ __param(2, (0, http_1.Cookie)()),
62
+ __metadata("design:type", Function),
63
+ __metadata("design:paramtypes", [rbac_1.User, token_dto_1.TokenDto, String]),
64
+ __metadata("design:returntype", Promise)
65
+ ], TwoFactorAuthController.prototype, "verifyToken", null);
66
+ TwoFactorAuthController = __decorate([
67
+ (0, http_1.BasePath)('user/auth'),
68
+ (0, http_2.Policy)(_2FaPolicy_1.TwoFacRouteEnabled)
69
+ ], TwoFactorAuthController);
70
+ exports.TwoFactorAuthController = TwoFactorAuthController;
71
+ //# sourceMappingURL=TwoFactorAuthController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TwoFactorAuthController.js","sourceRoot":"","sources":["../../src/controllers/TwoFactorAuthController.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,kDAA8C;AAC9C,wCAAyF;AACzF,wCAAmE;AACnE,wCAA6C;AAE7C,8CAAqC;AACrC,sDAA2D;AAC3D,0DAA2D;AAC3D,8CAAsD;AACtD,iCAAiC;AACjC,iEAA8D;AAC9D,oCAAyC;AACzC,0CAA6C;AAI7C,IAAa,uBAAuB,GAApC,MAAa,uBAAwB,SAAQ,qBAAc;IAWlD,KAAK,CAAC,WAAW,CAAS,MAAiB,EAAU,KAAe,EAAY,IAAY;QACjG,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAEjF,IAAI,MAAM,EAAE;YACV,OAAO,IAAI,mBAAY,CAAC,eAAe,CAAC,CAAC;SAC1C;QAED,MAAM,CAAC,WAAW,GAAG,gBAAQ,CAAC,GAAG,EAAE,CAAC;QACpC,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;QAEtB,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,mCAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAEzD,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE;YACpC,UAAU,EAAE,IAAI;YAChB,mBAAmB,EAAE,IAAI;SAC1B,CAAC,CAAC;QAEH,mBAAmB;QACnB,OAAO,IAAI,SAAE,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IACpC,CAAC;CACF,CAAA;AA7BC;IADC,IAAA,eAAU,EAAC,mBAAW,CAAC;8BACP,mBAAW;sDAAC;AAG7B;IADC,IAAA,iCAAiB,EAAC,cAAc,CAAC;8BACP,sBAAe;gEAAC;AAG3C;IADC,IAAA,iCAAiB,EAAC,oBAAoB,CAAC;8BACP,kCAAqB;sEAAC;AAGvD;IADC,IAAA,WAAI,EAAC,YAAY,CAAC;IACO,WAAA,IAAA,iBAAI,GAAE,CAAA;IAAqB,WAAA,IAAA,WAAI,GAAE,CAAA;IAAmB,WAAA,IAAA,aAAM,GAAE,CAAA;;qCAA7C,WAAS,EAAiB,oBAAQ;;0DAmB1E;AA9BU,uBAAuB;IAFnC,IAAA,eAAQ,EAAC,WAAW,CAAC;IACrB,IAAA,aAAM,EAAC,+BAAkB,CAAC;GACd,uBAAuB,CA+BnC;AA/BY,0DAAuB"}
@@ -6,5 +6,5 @@ export declare class UserController extends BaseController {
6
6
  protected CoockieSecret: string;
7
7
  protected SessionProvider: SessionProvider;
8
8
  refresh(user: UserModel, ssid: string): Promise<Ok>;
9
- newPassword(login: string, pwd: PasswordDto): Promise<Ok>;
9
+ newPassword(user: UserModel, pwd: PasswordDto): Promise<Ok>;
10
10
  }