@riao/authn-password 1.1.0 → 2.0.0

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.
package/CHANGELOG.md CHANGED
@@ -1 +1 @@
1
- # authn-password - Changelog
1
+ # authn-password - Changelog
package/LICENSE.md CHANGED
@@ -1,20 +1,20 @@
1
- Copyright (c) 2022 authn-password and others
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2022 authn-password and others
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md CHANGED
@@ -1,148 +1,148 @@
1
- # @riao/authn-password
2
-
3
- A TypeScript library that provides password-based authentication for the RIAO Identity and Access Management (IAM) framework. This driver implements secure password hashing and verification using bcrypt.
4
-
5
- ## Features
6
-
7
- - **Secure Password Hashing**: Uses bcrypt for secure password hashing with configurable salt rounds
8
- - **Principal Management**: Create and manage user principals with associated passwords
9
- - **Authentication**: Authenticate users with login credentials and passwords
10
- - **Flexible Hash Implementation**: Supports custom hash implementations via the `Hash` interface
11
- - **Database Agnostic**: Works with any database supported by the RIAO DBAL (Database Abstraction Layer)
12
- - **TypeScript Support**: Full TypeScript support with type safety
13
-
14
- ## Installation
15
-
16
- ```bash
17
- npm install @riao/authn-password @riao/iam @riao/dbal
18
- npm install --save-dev @riao/cli
19
- ```
20
-
21
- ## Database Migrations
22
-
23
- This driver requires the IAM password table to be created in your database. You can use the provided migrations:
24
-
25
- ```bash
26
- npx riao migration:create import-iam-tables
27
- ```
28
-
29
- Then, add the `AuthenticationPasswordMigrations` to your migration runner:
30
-
31
- `database/main/migrations/1234567890-import-iam-tables.ts`
32
- ```typescript
33
- import { AuthenticationPasswordMigrations } from 'authn-password';
34
-
35
- export default AuthenticationPasswordMigrations;
36
- ```
37
-
38
- ## Quick Start
39
-
40
- ### Basic Usage
41
-
42
- ```typescript
43
- import { PasswordAuthentication } from '@riao/authn-password';
44
- import { Principal } from '@riao/iam/auth';
45
- import { Database } from '@riao/dbal';
46
-
47
- // Define your user interface
48
- interface User extends Principal {
49
- login: string;
50
- }
51
-
52
- // Create an authentication service class
53
- class UserAuthentication extends PasswordAuthentication<User> {}
54
-
55
- // Initialize with your database
56
- const db = new YourDatabase();
57
- await db.init();
58
- await db.connect();
59
-
60
- const authService = new UserAuthentication({ db });
61
-
62
- // Create a new user with a password
63
- const userId = await authService.createPrincipal({
64
- login: 'john.doe',
65
- type: 'user',
66
- name: 'John Doe',
67
- password: 'securePassword123',
68
- });
69
-
70
- // Change a password
71
- await authService.changePassword(userId, 'newPassword123');
72
-
73
- // Authenticate a user
74
- const user = await authService.authenticate({
75
- login: 'john.doe',
76
- password: 'newPassword123',
77
- });
78
-
79
- if (user) {
80
- console.log(`Welcome ${user.name}!`);
81
- }
82
- else {
83
- console.log('Authentication failed');
84
- }
85
- ```
86
-
87
- ## API Reference
88
-
89
- ### PasswordAuthentication<TPrincipal>
90
-
91
- Abstract class that extends `Authentication<TPrincipal>` and adds password-based authentication.
92
-
93
- #### Constructor Options
94
-
95
- ```typescript
96
- interface PasswordAuthenticationOptions extends AuthOptions {
97
- hash?: Hash; // Optional custom hash implementation (defaults to bcrypt)
98
- }
99
- ```
100
-
101
- #### Methods
102
-
103
- - **createPrincipal(principal)**: Creates a new principal with a hashed password
104
- - Parameters: Principal data with `password` field
105
- - Returns: Principal ID
106
-
107
- - **authenticate(credentials)**: Authenticates a user with login and password
108
- - Parameters: Object with `login` and `password` fields
109
- - Returns: Principal object if successful, null if authentication fails
110
-
111
- - **passwordsRepo**: Query repository for accessing password records directly
112
-
113
- ### Password Record Schema
114
-
115
- Passwords are stored in the `iam_passwords` table:
116
-
117
- ```typescript
118
- interface Password {
119
- id?: string;
120
- principal_id: string; // Foreign key to principal
121
- password_hash: string; // Bcrypt hashed password
122
- deactivate_timestamp?: string;
123
- create_timestamp?: string;
124
- }
125
- ```
126
-
127
- ## Configuration
128
-
129
- ### Custom Hash Implementation
130
-
131
- You can provide a custom hash implementation:
132
-
133
- ```typescript
134
- import { Hash } from '@riao/iam/hash';
135
-
136
- class CustomHash extends Hash {
137
- // Implement your custom hashing logic
138
- }
139
-
140
- const authService = new UserAuthentication({
141
- db,
142
- hash: new CustomHash(),
143
- });
144
- ```
145
-
146
- ## Contributing & Development
147
-
148
- See [contributing.md](docs/contributing/contributing.md) for information on how to develop or contribute to this project!
1
+ # @riao/authn-password
2
+
3
+ A TypeScript library that provides password-based authentication for the RIAO Identity and Access Management (IAM) framework. This driver implements secure password hashing and verification using bcrypt.
4
+
5
+ ## Features
6
+
7
+ - **Secure Password Hashing**: Uses bcrypt for secure password hashing with configurable salt rounds
8
+ - **Principal Management**: Create and manage user principals with associated passwords
9
+ - **Authentication**: Authenticate users with login credentials and passwords
10
+ - **Flexible Hash Implementation**: Supports custom hash implementations via the `Hash` interface
11
+ - **Database Agnostic**: Works with any database supported by the RIAO DBAL (Database Abstraction Layer)
12
+ - **TypeScript Support**: Full TypeScript support with type safety
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @riao/authn-password @riao/iam @riao/dbal
18
+ npm install --save-dev @riao/cli
19
+ ```
20
+
21
+ ## Database Migrations
22
+
23
+ This driver requires the IAM password table to be created in your database. You can use the provided migrations:
24
+
25
+ ```bash
26
+ npx riao migration:create import-iam-tables
27
+ ```
28
+
29
+ Then, add the `AuthenticationPasswordMigrations` to your migration runner:
30
+
31
+ `database/main/migrations/1234567890-import-iam-tables.ts`
32
+ ```typescript
33
+ import { AuthenticationPasswordMigrations } from 'authn-password';
34
+
35
+ export default AuthenticationPasswordMigrations;
36
+ ```
37
+
38
+ ## Quick Start
39
+
40
+ ### Basic Usage
41
+
42
+ ```typescript
43
+ import { PasswordAuthentication } from '@riao/authn-password';
44
+ import { Principal } from '@riao/iam/auth';
45
+ import { Database } from '@riao/dbal';
46
+
47
+ // Define your user interface
48
+ interface User extends Principal {
49
+ login: string;
50
+ }
51
+
52
+ // Create an authentication service class
53
+ class UserAuthentication extends PasswordAuthentication<User> {}
54
+
55
+ // Initialize with your database
56
+ const db = new YourDatabase();
57
+ await db.init();
58
+ await db.connect();
59
+
60
+ const authService = new UserAuthentication({ db });
61
+
62
+ // Create a new user with a password
63
+ const userId = await authService.createPrincipal({
64
+ login: 'john.doe',
65
+ type: 'user',
66
+ name: 'John Doe',
67
+ password: 'securePassword123',
68
+ });
69
+
70
+ // Change a password
71
+ await authService.changePassword(userId, 'newPassword123');
72
+
73
+ // Authenticate a user
74
+ const user = await authService.authenticate({
75
+ login: 'john.doe',
76
+ password: 'newPassword123',
77
+ });
78
+
79
+ if (user) {
80
+ console.log(`Welcome ${user.name}!`);
81
+ }
82
+ else {
83
+ console.log('Authentication failed');
84
+ }
85
+ ```
86
+
87
+ ## API Reference
88
+
89
+ ### PasswordAuthentication<TPrincipal>
90
+
91
+ Abstract class that extends `Authentication<TPrincipal>` and adds password-based authentication.
92
+
93
+ #### Constructor Options
94
+
95
+ ```typescript
96
+ interface PasswordAuthenticationOptions extends AuthOptions {
97
+ hash?: Hash; // Optional custom hash implementation (defaults to bcrypt)
98
+ }
99
+ ```
100
+
101
+ #### Methods
102
+
103
+ - **createPrincipal(principal)**: Creates a new principal with a hashed password
104
+ - Parameters: Principal data with `password` field
105
+ - Returns: Principal ID
106
+
107
+ - **authenticate(credentials)**: Authenticates a user with login and password
108
+ - Parameters: Object with `login` and `password` fields
109
+ - Returns: Principal object if successful, null if authentication fails
110
+
111
+ - **passwordsRepo**: Query repository for accessing password records directly
112
+
113
+ ### Password Record Schema
114
+
115
+ Passwords are stored in the `iam_passwords` table:
116
+
117
+ ```typescript
118
+ interface Password {
119
+ id?: string;
120
+ principal_id: string; // Foreign key to principal
121
+ password_hash: string; // Bcrypt hashed password
122
+ deactivate_timestamp?: string;
123
+ create_timestamp?: string;
124
+ }
125
+ ```
126
+
127
+ ## Configuration
128
+
129
+ ### Custom Hash Implementation
130
+
131
+ You can provide a custom hash implementation:
132
+
133
+ ```typescript
134
+ import { Hash } from '@riao/crypto';
135
+
136
+ class CustomHash extends Hash {
137
+ // Implement your custom hashing logic
138
+ }
139
+
140
+ const authService = new UserAuthentication({
141
+ db,
142
+ hash: new CustomHash(),
143
+ });
144
+ ```
145
+
146
+ ## Contributing & Development
147
+
148
+ See [contributing.md](docs/contributing/contributing.md) for information on how to develop or contribute to this project!
@@ -1,15 +1,18 @@
1
1
  import { DatabaseRecordId, QueryRepository } from '@riao/dbal';
2
- import { Hash } from '@riao/iam/hash';
2
+ import { Hash } from '@riao/crypto';
3
3
  import { Principal } from '@riao/iam/auth';
4
- import { Authentication } from '@riao/iam/authentication';
5
- import { AuthOptions } from '@riao/iam/auth/auth';
4
+ import { Authentication, AuthenticationOptions } from '@riao/iam/authentication';
6
5
  import { Password } from './password';
7
- export interface PasswordAuthenticationOptions extends AuthOptions {
6
+ export interface PasswordAuthenticationOptions extends AuthenticationOptions {
8
7
  hash?: Hash;
8
+ maxFailedAttempts?: number;
9
+ lockoutDurationMs?: number;
9
10
  }
10
11
  export declare abstract class PasswordAuthentication<TPrincipal extends Principal> extends Authentication<TPrincipal> {
11
12
  passwordsRepo: QueryRepository<Password>;
12
13
  protected hash: Hash;
14
+ protected readonly maxFailedAttempts: number;
15
+ protected readonly lockoutDurationMs: number;
13
16
  constructor(options: PasswordAuthenticationOptions);
14
17
  createPrincipal(principal: Omit<TPrincipal, 'id' | 'create_timestamp'> & {
15
18
  password: string;
@@ -18,6 +21,8 @@ export declare abstract class PasswordAuthentication<TPrincipal extends Principa
18
21
  authenticate(credentials: Partial<TPrincipal & {
19
22
  password: string;
20
23
  }>): Promise<TPrincipal | null>;
24
+ protected recordPasswordFailure(password: Password): Promise<void>;
25
+ protected resetPasswordFailures(passwordId: DatabaseRecordId): Promise<void>;
21
26
  protected revokePasswords(principalId: DatabaseRecordId): Promise<void>;
22
27
  protected insertPassword(principalId: DatabaseRecordId, hash: string): Promise<void>;
23
28
  }
@@ -1,14 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PasswordAuthentication = void 0;
4
- const hash_1 = require("@riao/iam/hash");
4
+ const crypto_1 = require("@riao/crypto");
5
5
  const authentication_1 = require("@riao/iam/authentication");
6
6
  class PasswordAuthentication extends authentication_1.Authentication {
7
7
  passwordsRepo;
8
8
  hash;
9
+ maxFailedAttempts;
10
+ lockoutDurationMs;
9
11
  constructor(options) {
10
12
  super(options);
11
- this.hash = options.hash ?? new hash_1.Hash();
13
+ this.hash = options.hash ?? new crypto_1.Hash();
14
+ this.maxFailedAttempts = Math.max(1, options.maxFailedAttempts ?? 5);
15
+ this.lockoutDurationMs = options.lockoutDurationMs ?? 15 * 60 * 1000;
12
16
  this.passwordsRepo = options.db.getQueryRepository({
13
17
  table: 'iam_passwords',
14
18
  identifiedBy: 'id',
@@ -22,13 +26,19 @@ class PasswordAuthentication extends authentication_1.Authentication {
22
26
  return principalId;
23
27
  }
24
28
  async changePassword(principalId, newPassword) {
25
- // eslint-disable-next-line no-console
26
- console.log('Changing password for principal ID:', principalId, newPassword);
27
29
  const hash = await this.hash.make(newPassword);
28
30
  await this.revokePasswords(principalId);
29
31
  await this.insertPassword(principalId, hash);
30
32
  }
31
33
  async authenticate(credentials) {
34
+ const attempt = {
35
+ scheme: 'password',
36
+ subject: String(credentials.login ?? ''),
37
+ };
38
+ const protection = await this.beforeAuthenticationAttempt(attempt);
39
+ if (!protection.allowed) {
40
+ return null;
41
+ }
32
42
  const principal = await this.findActivePrincipal({
33
43
  where: {
34
44
  login: credentials.login,
@@ -44,8 +54,67 @@ class PasswordAuthentication extends authentication_1.Authentication {
44
54
  if (!passwordRecord) {
45
55
  return null;
46
56
  }
57
+ if (passwordRecord.locked_until &&
58
+ passwordRecord.locked_until <= new Date()) {
59
+ await this.passwordsRepo.update({
60
+ set: {
61
+ failed_authentication_count: 0,
62
+ locked_until: null,
63
+ },
64
+ where: { id: passwordRecord.id },
65
+ });
66
+ }
67
+ else if (passwordRecord.locked_until &&
68
+ passwordRecord.locked_until > new Date()) {
69
+ return null;
70
+ }
47
71
  const isValid = await this.hash.check(credentials.password, passwordRecord?.password_hash);
48
- return isValid ? principal : null;
72
+ if (!isValid) {
73
+ await this.recordAuthenticationFailure(attempt);
74
+ await this.recordPasswordFailure(passwordRecord);
75
+ return null;
76
+ }
77
+ await this.recordAuthenticationSuccess(attempt);
78
+ await this.resetPasswordFailures(passwordRecord.id);
79
+ return principal;
80
+ }
81
+ async recordPasswordFailure(password) {
82
+ if (password.locked_until &&
83
+ password.locked_until <= new Date()) {
84
+ await this.passwordsRepo.update({
85
+ set: {
86
+ failed_authentication_count: 0,
87
+ locked_until: null,
88
+ },
89
+ where: { id: password.id },
90
+ });
91
+ }
92
+ await this.passwordsRepo.increment({
93
+ column: 'failed_authentication_count',
94
+ where: { id: password.id },
95
+ });
96
+ const updatedPassword = await this.passwordsRepo.findOne({
97
+ where: { id: password.id },
98
+ });
99
+ if (updatedPassword &&
100
+ (updatedPassword.failed_authentication_count ?? 0) >=
101
+ this.maxFailedAttempts) {
102
+ await this.passwordsRepo.update({
103
+ set: {
104
+ locked_until: new Date(Date.now() + this.lockoutDurationMs),
105
+ },
106
+ where: { id: password.id },
107
+ });
108
+ }
109
+ }
110
+ async resetPasswordFailures(passwordId) {
111
+ await this.passwordsRepo.update({
112
+ set: {
113
+ failed_authentication_count: 0,
114
+ locked_until: null,
115
+ },
116
+ where: { id: passwordId },
117
+ });
49
118
  }
50
119
  async revokePasswords(principalId) {
51
120
  await this.passwordsRepo.update({
@@ -61,6 +130,8 @@ class PasswordAuthentication extends authentication_1.Authentication {
61
130
  record: {
62
131
  principal_id: principalId,
63
132
  password_hash: hash,
133
+ failed_authentication_count: 0,
134
+ locked_until: null,
64
135
  },
65
136
  });
66
137
  }
@@ -1 +1 @@
1
- {"version":3,"file":"authentication-password.js","sourceRoot":"","sources":["../../src/authentication-password.ts"],"names":[],"mappings":";;;AACA,yCAAsC;AAEtC,6DAA0D;AAQ1D,MAAsB,sBAEpB,SAAQ,+BAA0B;IAC5B,aAAa,CAA4B;IAEtC,IAAI,CAAO;IAErB,YAAmB,OAAsC;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,IAAI,WAAI,EAAE,CAAC;QACvC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,EAAE,CAAC,kBAAkB,CAAW;YAC5D,KAAK,EAAE,eAAe;YACtB,YAAY,EAAE,IAAI;SAClB,CAAC,CAAC;IACJ,CAAC;IAEe,KAAK,CAAC,eAAe,CACpC,SAEC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACtD,OAAQ,SAAmC,CAAC,QAAQ,CAAC;QAErD,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC3D,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAE7C,OAAO,WAAW,CAAC;IACpB,CAAC;IAEM,KAAK,CAAC,cAAc,CAC1B,WAA6B,EAC7B,WAAmB;QAEnB,sCAAsC;QACtC,OAAO,CAAC,GAAG,CACV,qCAAqC,EACrC,WAAW,EACX,WAAW,CACX,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAE/C,MAAM,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;QACxC,MAAM,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAC9C,CAAC;IAEM,KAAK,CAAC,YAAY,CACxB,WAAuD;QAEvD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC;YAChD,KAAK,EAAc;gBAClB,KAAK,EAAE,WAAW,CAAC,KAAK;aACxB;SACD,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;YACvD,KAAK,EAAE,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE;YACjE,OAAO,EAAE,EAAE,gBAAgB,EAAE,MAAM,EAAE;SACrC,CAAC,CAAC;QAEH,IAAI,CAAC,cAAc,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CACpC,WAAW,CAAC,QAAkB,EAC9B,cAAc,EAAE,aAAuB,CACvC,CAAC;QAEF,OAAO,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;IACnC,CAAC;IAES,KAAK,CAAC,eAAe,CAC9B,WAA6B;QAE7B,MAAM,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;YAC/B,GAAG,EAAE,EAAE,oBAAoB,EAAE,IAAI,IAAI,EAAE,EAAE;YACzC,KAAK,EAAE;gBACN,YAAY,EAAE,WAAqB;gBACnC,oBAAoB,EAAE,IAAI;aAC1B;SACD,CAAC,CAAC;IACJ,CAAC;IAES,KAAK,CAAC,cAAc,CAC7B,WAA6B,EAC7B,IAAY;QAEZ,MAAM,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC;YAClC,MAAM,EAAE;gBACP,YAAY,EAAE,WAAqB;gBACnC,aAAa,EAAE,IAAI;aACnB;SACD,CAAC,CAAC;IACJ,CAAC;CACD;AAnGD,wDAmGC"}
1
+ {"version":3,"file":"authentication-password.js","sourceRoot":"","sources":["../../src/authentication-password.ts"],"names":[],"mappings":"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"}
@@ -25,6 +25,17 @@ class CreatePasswordsTable extends dbal_1.Migration {
25
25
  type: dbal_1.ColumnType.TIMESTAMP,
26
26
  required: false,
27
27
  },
28
+ {
29
+ name: 'failed_authentication_count',
30
+ type: dbal_1.ColumnType.INT,
31
+ required: true,
32
+ default: 0,
33
+ },
34
+ {
35
+ name: 'locked_until',
36
+ type: dbal_1.ColumnType.TIMESTAMP,
37
+ required: false,
38
+ },
28
39
  ],
29
40
  });
30
41
  }
@@ -1 +1 @@
1
- {"version":3,"file":"001-create-passwords-table.js","sourceRoot":"","sources":["../../../src/migrations/001-create-passwords-table.ts"],"names":[],"mappings":";;;AAAA,wDAIgC;AAChC,qCAAmD;AAEnD,MAAa,oBAAqB,SAAQ,gBAAS;IACzC,KAAK,CAAC,EAAE;QAChB,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;YAC1B,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE;gBACR,2BAAa;gBACb;oBACC,IAAI,EAAE,cAAc;oBACpB,IAAI,EAAE,iBAAU,CAAC,IAAI;oBACrB,EAAE,EAAE;wBACH,eAAe,EAAE,gBAAgB;wBACjC,gBAAgB,EAAE,IAAI;wBACtB,QAAQ,EAAE,SAAS;qBACnB;iBACD;gBACD,EAAE,GAAG,4BAAc,EAAE,IAAI,EAAE,eAAe,EAAE;gBAC5C,mCAAqB;gBACrB;oBACC,IAAI,EAAE,sBAAsB;oBAC5B,IAAI,EAAE,iBAAU,CAAC,SAAS;oBAC1B,QAAQ,EAAE,KAAK;iBACf;aACD;SACD,CAAC,CAAC;IACJ,CAAC;IAEQ,KAAK,CAAC,IAAI;QAClB,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;YACxB,MAAM,EAAE,eAAe;SACvB,CAAC,CAAC;IACJ,CAAC;CACD;AA/BD,oDA+BC"}
1
+ {"version":3,"file":"001-create-passwords-table.js","sourceRoot":"","sources":["../../../src/migrations/001-create-passwords-table.ts"],"names":[],"mappings":";;;AAAA,wDAIgC;AAChC,qCAAmD;AAEnD,MAAa,oBAAqB,SAAQ,gBAAS;IACzC,KAAK,CAAC,EAAE;QAChB,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC;YAC1B,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE;gBACR,2BAAa;gBACb;oBACC,IAAI,EAAE,cAAc;oBACpB,IAAI,EAAE,iBAAU,CAAC,IAAI;oBACrB,EAAE,EAAE;wBACH,eAAe,EAAE,gBAAgB;wBACjC,gBAAgB,EAAE,IAAI;wBACtB,QAAQ,EAAE,SAAS;qBACnB;iBACD;gBACD,EAAE,GAAG,4BAAc,EAAE,IAAI,EAAE,eAAe,EAAE;gBAC5C,mCAAqB;gBACrB;oBACC,IAAI,EAAE,sBAAsB;oBAC5B,IAAI,EAAE,iBAAU,CAAC,SAAS;oBAC1B,QAAQ,EAAE,KAAK;iBACf;gBACD;oBACC,IAAI,EAAE,6BAA6B;oBACnC,IAAI,EAAE,iBAAU,CAAC,GAAG;oBACpB,QAAQ,EAAE,IAAI;oBACd,OAAO,EAAE,CAAC;iBACV;gBACD;oBACC,IAAI,EAAE,cAAc;oBACpB,IAAI,EAAE,iBAAU,CAAC,SAAS;oBAC1B,QAAQ,EAAE,KAAK;iBACf;aACD;SACD,CAAC,CAAC;IACJ,CAAC;IAEQ,KAAK,CAAC,IAAI;QAClB,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;YACxB,MAAM,EAAE,eAAe;SACvB,CAAC,CAAC;IACJ,CAAC;CACD;AA1CD,oDA0CC"}
@@ -0,0 +1,5 @@
1
+ import { Migration } from '@riao/dbal';
2
+ export declare class AddPasswordAuthenticationProtection extends Migration {
3
+ up(): Promise<void>;
4
+ down(): Promise<void>;
5
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AddPasswordAuthenticationProtection = void 0;
4
+ const dbal_1 = require("@riao/dbal");
5
+ class AddPasswordAuthenticationProtection extends dbal_1.Migration {
6
+ async up() {
7
+ await this.ddl.addColumns({
8
+ table: 'iam_passwords',
9
+ columns: [
10
+ {
11
+ name: 'failed_authentication_count',
12
+ type: dbal_1.ColumnType.INT,
13
+ required: true,
14
+ default: 0,
15
+ },
16
+ ],
17
+ });
18
+ await this.ddl.addColumns({
19
+ table: 'iam_passwords',
20
+ columns: [
21
+ {
22
+ name: 'locked_until',
23
+ type: dbal_1.ColumnType.TIMESTAMP,
24
+ required: false,
25
+ },
26
+ ],
27
+ });
28
+ }
29
+ async down() {
30
+ await this.ddl.dropColumn({
31
+ table: 'iam_passwords',
32
+ column: 'locked_until',
33
+ });
34
+ await this.ddl.dropColumn({
35
+ table: 'iam_passwords',
36
+ column: 'failed_authentication_count',
37
+ });
38
+ }
39
+ }
40
+ exports.AddPasswordAuthenticationProtection = AddPasswordAuthenticationProtection;
41
+ //# sourceMappingURL=002-add-password-authentication-protection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"002-add-password-authentication-protection.js","sourceRoot":"","sources":["../../../src/migrations/002-add-password-authentication-protection.ts"],"names":[],"mappings":";;;AAAA,qCAAmD;AAEnD,MAAa,mCAAoC,SAAQ,gBAAS;IACxD,KAAK,CAAC,EAAE;QAChB,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YACzB,KAAK,EAAE,eAAe;YACtB,OAAO,EAAE;gBACR;oBACC,IAAI,EAAE,6BAA6B;oBACnC,IAAI,EAAE,iBAAU,CAAC,GAAG;oBACpB,QAAQ,EAAE,IAAI;oBACd,OAAO,EAAE,CAAC;iBACV;aACD;SACD,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YACzB,KAAK,EAAE,eAAe;YACtB,OAAO,EAAE;gBACR;oBACC,IAAI,EAAE,cAAc;oBACpB,IAAI,EAAE,iBAAU,CAAC,SAAS;oBAC1B,QAAQ,EAAE,KAAK;iBACf;aACD;SACD,CAAC,CAAC;IACJ,CAAC;IAEQ,KAAK,CAAC,IAAI;QAClB,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YACzB,KAAK,EAAE,eAAe;YACtB,MAAM,EAAE,cAAc;SACtB,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YACzB,KAAK,EAAE,eAAe;YACtB,MAAM,EAAE,6BAA6B;SACrC,CAAC,CAAC;IACJ,CAAC;CACD;AAnCD,kFAmCC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riao/authn-password",
3
- "version": "1.1.0",
3
+ "version": "2.0.0",
4
4
  "description": "Password driver for Riao",
5
5
  "typescript-template": {
6
6
  "base": "1.0.1",
@@ -9,8 +9,9 @@
9
9
  },
10
10
  "scripts": {},
11
11
  "dependencies": {
12
- "@riao/dbal": "^3.8.0",
13
- "@riao/iam": "^3.0.0",
12
+ "@riao/crypto": "^1.1.1",
13
+ "@riao/dbal": "^3.12.0",
14
+ "@riao/iam": "^4.0.0",
14
15
  "bcrypt": "^6.0.0"
15
16
  },
16
17
  "repository": {
package/password.d.ts CHANGED
@@ -4,4 +4,6 @@ export interface Password {
4
4
  password_hash: string;
5
5
  create_timestamp: Date;
6
6
  deactivate_timestamp?: Date | null;
7
+ failed_authentication_count?: number;
8
+ locked_until?: Date | null;
7
9
  }