auth0-password-policies 1.1.1 → 2.1.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/README.md CHANGED
@@ -36,8 +36,10 @@ const { createRulesFromOptions } = require('auth0-password-policies');
36
36
 
37
37
  const passwordOptions = {
38
38
  character_types: ["uppercase","lowercase","number","special"],
39
- "require_3of4_character_types": true,
40
- identical_characters: "disallow"
39
+ character_type_rule: "three_of_four",
40
+ identical_characters: "block",
41
+ sequential_characters: "block",
42
+ max_length_exceeded: "error"
41
43
  };
42
44
 
43
45
  const rules = createRulesFromOptions(passwordOptions);
@@ -52,6 +54,8 @@ console.log(customPolicy.toString());
52
54
  * * numbers (i.e. 0-9)
53
55
  * * special characters (e.g. !@#$%^&*)
54
56
  * * No more than 2 identical characters in a row (e.g., "aaa" not allowed)
57
+ * * No more than 2 sequential alphanumeric characters (e.g., "abc" not allowed)
58
+ * * Maximum password length exceeded
55
59
  */
56
60
  ```
57
61
 
package/index.js CHANGED
@@ -46,8 +46,10 @@ const CHARACTER_TYPES = {
46
46
  * @typedef {Object} PasswordOptions
47
47
  * @property {number} [min_length=15] - Minimum password length (1-72)
48
48
  * @property {Array<'uppercase'|'lowercase'|'number'|'special'>} [character_types=[]] - Required character types
49
- * @property {boolean} [require_3of4_character_types=false] - Whether to require 3 out of 4 character types (requires all 4 types to be specified)
50
- * @property {'allow'|'disallow'} [identical_characters='disallow'] - Whether to allow >2 identical consecutive characters
49
+ * @property {'all'|'three_of_four'} [character_type_rule='all'] - How many character types are required
50
+ * @property {'allow'|'block'} [identical_characters='allow'] - Whether to allow >2 identical consecutive characters
51
+ * @property {'allow'|'block'} [sequential_characters='allow'] - Whether to allow sequential_characters (increasing or decreasing) alphanumeric characters.
52
+ * @property {'error'|'truncate'} [max_length_exceeded='error'] - Behavior when password exceeds max length of 72 bytes
51
53
  */
52
54
 
53
55
  /**
@@ -58,8 +60,10 @@ const CHARACTER_TYPES = {
58
60
  const DEFAULT_PASSWORD_OPTIONS = {
59
61
  min_length: 15,
60
62
  character_types: [],
61
- require_3of4_character_types: false,
62
- identical_characters: "disallow",
63
+ character_type_rule: "all",
64
+ identical_characters: "allow",
65
+ sequential_characters: "allow",
66
+ max_length_exceeded: "error"
63
67
  };
64
68
 
65
69
  /**
@@ -76,8 +80,10 @@ function createRulesFromOptions(options = {}) {
76
80
  const {
77
81
  min_length: minLength,
78
82
  character_types: requiredTypes,
79
- require_3of4_character_types: require3of4,
83
+ character_type_rule: characterTypeRule,
80
84
  identical_characters: identicalChars,
85
+ sequential_characters: sequentialChars,
86
+ max_length_exceeded: maxLength
81
87
  } = { ...DEFAULT_PASSWORD_OPTIONS, ...options };
82
88
 
83
89
  // Validate min_length is within acceptable range
@@ -88,7 +94,8 @@ function createRulesFromOptions(options = {}) {
88
94
  // Handle min_length
89
95
  rules.length = { minLength: minLength };
90
96
 
91
- // Validate require_3of4_character_types prerequisite
97
+ // Validate '3 of 4' prerequisite
98
+ const require3of4 = characterTypeRule === "three_of_four";
92
99
  if (require3of4) {
93
100
  const hasAllFourTypes = Object.values(CHARACTER_TYPES).every(function (
94
101
  type
@@ -98,7 +105,7 @@ function createRulesFromOptions(options = {}) {
98
105
 
99
106
  if (!hasAllFourTypes) {
100
107
  throw new Error(
101
- `require_3of4_character_types can only be used when all four character types (${Object.values(
108
+ `'three_of_four' character_type_rule can only be used when all four character types (${Object.values(
102
109
  CHARACTER_TYPES
103
110
  ).join(", ")}) are selected`
104
111
  );
@@ -135,10 +142,18 @@ function createRulesFromOptions(options = {}) {
135
142
  }
136
143
  }
137
144
 
138
- if (identicalChars === "disallow") {
145
+ if (identicalChars === "block") {
139
146
  rules.identicalChars = { max: 2 };
140
147
  }
141
148
 
149
+ if (sequentialChars === "block") {
150
+ rules.sequentialChars = { max: 2 }
151
+ }
152
+
153
+ if (maxLength === "error") {
154
+ rules.maxLength = { maxBytes: 72 };
155
+ }
156
+
142
157
  return rules;
143
158
  }
144
159
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auth0-password-policies",
3
- "version": "1.1.1",
3
+ "version": "2.1.0",
4
4
  "main": "index.js",
5
5
  "repository": "git@github.com:auth0/auth0-password-policies.git",
6
6
  "author": "Shaun Starsprung <shaun.starsprung@auth0.com>",
@@ -12,6 +12,6 @@
12
12
  "jest": "^29.0.0"
13
13
  },
14
14
  "dependencies": {
15
- "password-sheriff": "^1.1.0"
15
+ "password-sheriff": "^1.3.0"
16
16
  }
17
17
  }
package/test/test.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const policies = require("..");
2
2
  const { createRulesFromOptions } = policies;
3
+ const { PasswordPolicy } = require("password-sheriff");
3
4
 
4
5
  describe("password policies", function () {
5
6
  describe("main export", function () {
@@ -23,6 +24,7 @@ describe("password policies", function () {
23
24
  const auth0Config1 = {
24
25
  min_length: 1,
25
26
  identical_characters: "allow",
27
+ max_length_exceeded: "truncate",
26
28
  };
27
29
  const rules = createRulesFromOptions(auth0Config1);
28
30
  expect(rules).toEqual({
@@ -34,6 +36,7 @@ describe("password policies", function () {
34
36
  const auth0Config72 = {
35
37
  min_length: 72,
36
38
  identical_characters: "allow",
39
+ max_length_exceeded: "truncate",
37
40
  };
38
41
  const rules72 = createRulesFromOptions(auth0Config72);
39
42
  expect(rules72).toEqual({
@@ -59,6 +62,7 @@ describe("password policies", function () {
59
62
  character_types: ["lowercase", "uppercase", "number", "special"],
60
63
  identical_characters: "allow",
61
64
  min_length: 4,
65
+ max_length_exceeded: "truncate",
62
66
  };
63
67
  const rules = createRulesFromOptions(auth0Config);
64
68
  expect(rules).toHaveProperty("length");
@@ -76,13 +80,14 @@ describe("password policies", function () {
76
80
  });
77
81
  });
78
82
 
79
- describe("require_3of4_character_types", function () {
80
- it("should enforce 3 out of 4 character types when all 4 types are specified", function () {
83
+ describe("character_type_rule", function () {
84
+ it("when set to 'three_of_four', should enforce 3 out of 4 character types when all 4 types are specified", function () {
81
85
  const auth0Config = {
82
86
  character_types: ["lowercase", "uppercase", "number", "special"],
83
- require_3of4_character_types: true,
87
+ character_type_rule: "three_of_four",
84
88
  identical_characters: "allow",
85
89
  min_length: 3,
90
+ max_length_exceeded: "truncate",
86
91
  };
87
92
  const rules = createRulesFromOptions(auth0Config);
88
93
  expect(rules).toHaveProperty("length");
@@ -100,15 +105,16 @@ describe("password policies", function () {
100
105
  });
101
106
  });
102
107
 
103
- it("should throw an error when require_3of4_character_types is used without all 4 character types", function () {
108
+ it("when set to 'three_of_four', should throw an error when all 4 character types are NOT specified", function () {
104
109
  expect(function () {
105
110
  const auth0Config = {
106
111
  character_types: ["lowercase", "uppercase"],
107
- require_3of4_character_types: true,
112
+ character_type_rule: "three_of_four",
113
+ max_length_exceeded: "error",
108
114
  };
109
115
  createRulesFromOptions(auth0Config);
110
116
  }).toThrow(
111
- "require_3of4_character_types can only be used when all four character types (lowercase, uppercase, number, special) are selected"
117
+ "'three_of_four' character_type_rule can only be used when all four character types (lowercase, uppercase, number, special) are selected"
112
118
  );
113
119
  });
114
120
  });
@@ -116,7 +122,8 @@ describe("password policies", function () {
116
122
  describe("identical_characters", function () {
117
123
  it("should disallow more than 2 identical characters when specified", function () {
118
124
  const auth0Config = {
119
- identical_characters: "disallow",
125
+ identical_characters: "block",
126
+ max_length_exceeded: "error",
120
127
  };
121
128
  const rules = createRulesFromOptions(auth0Config);
122
129
  expect(rules).toEqual({
@@ -126,12 +133,106 @@ describe("password policies", function () {
126
133
  identicalChars: {
127
134
  max: 2,
128
135
  },
136
+ maxLength: {
137
+ maxBytes: 72,
138
+ },
129
139
  });
130
140
  });
131
141
 
132
142
  it("should allow more than 2 identical characters when specified", function () {
133
143
  const auth0Config = {
134
144
  identical_characters: "allow",
145
+ max_length_exceeded: "error",
146
+ };
147
+ const rules = createRulesFromOptions(auth0Config);
148
+ expect(rules).toEqual({
149
+ length: {
150
+ minLength: 15,
151
+ },
152
+ maxLength: {
153
+ maxBytes: 72,
154
+ },
155
+ });
156
+ });
157
+ });
158
+
159
+ describe("sequential_characters", function () {
160
+ it("should disallow more than 2 sequential characters when specified (set to block)", function () {
161
+ const auth0Config = {
162
+ sequential_characters: "block",
163
+ };
164
+ const rules = createRulesFromOptions(auth0Config);
165
+ expect(rules).toEqual({
166
+ length: {
167
+ minLength: 15,
168
+ },
169
+ sequentialChars: {
170
+ max: 2,
171
+ },
172
+ maxLength: {
173
+ maxBytes: 72,
174
+ },
175
+ });
176
+ });
177
+
178
+ it("should allow more than 2 sequential characters when specified (set to allow)", function () {
179
+ const auth0Config = {
180
+ sequential_characters: "allow",
181
+ };
182
+ const rules = createRulesFromOptions(auth0Config);
183
+ expect(rules).toEqual({
184
+ length: {
185
+ minLength: 15,
186
+ },
187
+ maxLength: {
188
+ maxBytes: 72,
189
+ },
190
+ });
191
+ });
192
+
193
+ it("should correctly validate a password when sequential_characters is set to allow", function () {
194
+ const auth0Config = {
195
+ min_length: 2,
196
+ sequential_characters: "allow",
197
+ };
198
+ const rules = createRulesFromOptions(auth0Config);
199
+ const policy = new PasswordPolicy(rules);
200
+ const result = policy.check("abcde");
201
+ expect(result).toBe(true);
202
+ });
203
+
204
+ it("should correctly validate a password when sequential_characters is set to block", function () {
205
+ const auth0Config = {
206
+ min_length: 2,
207
+ sequential_characters: "block",
208
+ };
209
+ const rules = createRulesFromOptions(auth0Config);
210
+ const policy = new PasswordPolicy(rules);
211
+ const result = policy.check("abcde");
212
+
213
+ expect(result).toBe(false);
214
+ });
215
+ });
216
+
217
+ describe("max_length_exceeded", function () {
218
+ it("should disallow more than 72 bytes when creating password if max_length_exceeded is set to error", function () {
219
+ const auth0Config = {
220
+ max_length_exceeded: "error",
221
+ };
222
+ const rules = createRulesFromOptions(auth0Config);
223
+ expect(rules).toEqual({
224
+ length: {
225
+ minLength: 15,
226
+ },
227
+ maxLength: {
228
+ maxBytes: 72,
229
+ },
230
+ });
231
+ });
232
+
233
+ it("should not set a maxLength on rules when max_length_exceeded is set to truncate", function () {
234
+ const auth0Config = {
235
+ max_length_exceeded: "truncate",
135
236
  };
136
237
  const rules = createRulesFromOptions(auth0Config);
137
238
  expect(rules).toEqual({
@@ -140,6 +241,30 @@ describe("password policies", function () {
140
241
  },
141
242
  });
142
243
  });
244
+
245
+ it("should correctly validate a password when max_length_exceeded is set to error", function () {
246
+ const auth0Config = {
247
+ min_length: 2,
248
+ max_length_exceeded: "error",
249
+ };
250
+ const rules = createRulesFromOptions(auth0Config);
251
+ const policy = new PasswordPolicy(rules);
252
+ const password = "a".repeat(100);
253
+ const result = policy.check(password);
254
+ expect(result).toBe(false);
255
+ });
256
+
257
+ it("should correctly validate a password when max_length_exceeded is set to truncate", function () {
258
+ const auth0Config = {
259
+ min_length: 2,
260
+ max_length_exceeded: "truncate",
261
+ };
262
+ const rules = createRulesFromOptions(auth0Config);
263
+ const policy = new PasswordPolicy(rules);
264
+ const password = "a".repeat(100);
265
+ const result = policy.check(password);
266
+ expect(result).toBe(true);
267
+ });
143
268
  });
144
269
 
145
270
  describe("default values", function () {
@@ -150,8 +275,8 @@ describe("password policies", function () {
150
275
  length: {
151
276
  minLength: 15,
152
277
  },
153
- identicalChars: {
154
- max: 2,
278
+ maxLength: {
279
+ maxBytes: 72,
155
280
  },
156
281
  });
157
282
  });
@@ -160,6 +285,8 @@ describe("password policies", function () {
160
285
  const auth0Config = {
161
286
  min_length: 5,
162
287
  identical_characters: "allow",
288
+ sequential_characters: "allow",
289
+ max_length_exceeded: "truncate",
163
290
  };
164
291
  const rules = createRulesFromOptions(auth0Config);
165
292
  expect(rules).toEqual({