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 +6 -2
- package/index.js +23 -8
- package/package.json +2 -2
- package/test/test.js +136 -9
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
|
-
"
|
|
40
|
-
identical_characters: "
|
|
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 {
|
|
50
|
-
* @property {'allow'|'
|
|
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
|
-
|
|
62
|
-
identical_characters: "
|
|
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
|
-
|
|
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
|
|
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
|
-
`
|
|
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 === "
|
|
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": "
|
|
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.
|
|
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("
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
112
|
+
character_type_rule: "three_of_four",
|
|
113
|
+
max_length_exceeded: "error",
|
|
108
114
|
};
|
|
109
115
|
createRulesFromOptions(auth0Config);
|
|
110
116
|
}).toThrow(
|
|
111
|
-
"
|
|
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: "
|
|
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
|
-
|
|
154
|
-
|
|
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({
|