check-password-strength
Advanced tools
Comparing version 2.0.10 to 3.0.0
@@ -17,2 +17,4 @@ export interface Option<V> { | ||
export const owaspSymbols: string; | ||
export type DiversityType = "lowercase" | "uppercase" | "symbol" | "number"; | ||
@@ -30,3 +32,3 @@ | ||
options?: Options<V>, | ||
allowedSymbols?: string, | ||
restrictSymbolsTo?: string | undefined, | ||
): Result<V>; |
@@ -0,1 +1,17 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
function escapeStringRegexp(string) { | ||
if (typeof string !== 'string') { | ||
throw new TypeError('Expected a string'); | ||
} | ||
// Escape characters with special meaning either inside or outside character sets. | ||
// Use a simple backslash escape when it’s always valid, and a `\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar. | ||
return string | ||
.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&') | ||
.replace(/-/g, '\\x2d'); | ||
} | ||
const defaultOptions = [ | ||
@@ -6,3 +22,3 @@ { | ||
minDiversity: 0, | ||
minLength: 0 | ||
minLength: 0, | ||
}, | ||
@@ -13,3 +29,3 @@ { | ||
minDiversity: 2, | ||
minLength: 6 | ||
minLength: 8, | ||
}, | ||
@@ -20,3 +36,3 @@ { | ||
minDiversity: 4, | ||
minLength: 8 | ||
minLength: 10, | ||
}, | ||
@@ -27,50 +43,53 @@ { | ||
minDiversity: 4, | ||
minLength: 10 | ||
} | ||
] | ||
minLength: 12, | ||
}, | ||
]; | ||
const passwordStrength = (password, options = defaultOptions, allowedSymbols = "!\"#\$%&'\(\)\*\+,-\./:;<=>\?@\[\\\\\\]\^_`\{|\}~") => { | ||
const owaspSymbols = "!\"#$%&'()*+,-./\\:;<=>?@[]^_`{|}~"; | ||
let passwordCopy = password || '' | ||
const passwordStrength = ( | ||
password, | ||
options = defaultOptions, | ||
restrictSymbolsTo | ||
) => { | ||
options[0].minDiversity = 0; | ||
options[0].minLength = 0; | ||
options[0].minDiversity = 0, | ||
options[0].minLength = 0 | ||
// prevent [a-z] to match null and compute length | ||
const _password = password ?? ""; | ||
const rules = [ | ||
{ | ||
key: "lowercase", | ||
regex: "[a-z]", | ||
message: 'lowercase' | ||
}, | ||
{ | ||
regex: '[A-Z]', | ||
message: 'uppercase' | ||
key: "uppercase", | ||
regex: "[A-Z]", | ||
}, | ||
{ | ||
regex: '[0-9]', | ||
message: 'number' | ||
key: "number", | ||
regex: "[0-9]", | ||
}, | ||
] | ||
{ | ||
key: "symbol", | ||
regex: restrictSymbolsTo ? `[${escapeStringRegexp(restrictSymbolsTo)}]` : "[^a-zA-Z0-9]", | ||
}, | ||
]; | ||
if (allowedSymbols) { | ||
rules.push({ | ||
regex: `[${allowedSymbols}]`, | ||
message: 'symbol' | ||
}) | ||
} | ||
let strength = {}; | ||
let strength = {} | ||
strength.contains = rules | ||
.filter(rule => new RegExp(`${rule.regex}`).test(passwordCopy)) | ||
.map(rule => rule.message) | ||
.filter((rule) => new RegExp(`${rule.regex}`).test(_password)) | ||
.map((rule) => rule.key); | ||
strength.length = passwordCopy.length; | ||
strength.length = _password.length; | ||
let fulfilledOptions = options | ||
.filter(option => strength.contains.length >= option.minDiversity) | ||
.filter(option => strength.length >= option.minLength) | ||
.filter((option) => strength.contains.length >= option.minDiversity) | ||
.filter((option) => strength.length >= option.minLength) | ||
.sort((o1, o2) => o2.id - o1.id) | ||
.map(option => ({ id: option.id, value: option.value })) | ||
.map((option) => ({ id: option.id, value: option.value })); | ||
Object.assign(strength, fulfilledOptions[0]) | ||
Object.assign(strength, fulfilledOptions[0]); | ||
@@ -80,4 +99,7 @@ return strength; | ||
module.exports = { passwordStrength, defaultOptions } | ||
module.exports.passwordStrength = passwordStrength | ||
module.exports.defaultOptions = defaultOptions | ||
var index = { passwordStrength, defaultOptions, owaspSymbols }; | ||
exports.default = index; | ||
exports.defaultOptions = defaultOptions; | ||
exports.owaspSymbols = owaspSymbols; | ||
exports.passwordStrength = passwordStrength; |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).checkPasswordStrength={})}(this,(function(e){"use strict";function t(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var n={exports:{}};const i=[{id:0,value:"Too weak",minDiversity:0,minLength:0},{id:1,value:"Weak",minDiversity:2,minLength:6},{id:2,value:"Medium",minDiversity:4,minLength:8},{id:3,value:"Strong",minDiversity:4,minLength:10}],s=(e,t=i,n="!\"#$%&'()*+,-./:;<=>?@[\\\\\\]^_`{|}~")=>{let s=e||"";t[0].minDiversity=0,t[0].minLength=0;const r=[{regex:"[a-z]",message:"lowercase"},{regex:"[A-Z]",message:"uppercase"},{regex:"[0-9]",message:"number"}];n&&r.push({regex:`[${n}]`,message:"symbol"});let o={};o.contains=r.filter((e=>new RegExp(`${e.regex}`).test(s))).map((e=>e.message)),o.length=s.length;let a=t.filter((e=>o.contains.length>=e.minDiversity)).filter((e=>o.length>=e.minLength)).sort(((e,t)=>t.id-e.id)).map((e=>({id:e.id,value:e.value})));return Object.assign(o,a[0]),o};n.exports={passwordStrength:s,defaultOptions:i};var r=n.exports.passwordStrength=s,o=n.exports.defaultOptions=i,a=t(n.exports);e.default=a,e.defaultOptions=o,e.passwordStrength=r,Object.defineProperty(e,"__esModule",{value:!0})})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).checkPasswordStrength={})}(this,(function(e){"use strict";function t(e){if("string"!=typeof e)throw new TypeError("Expected a string");return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}const i=[{id:0,value:"Too weak",minDiversity:0,minLength:0},{id:1,value:"Weak",minDiversity:2,minLength:8},{id:2,value:"Medium",minDiversity:4,minLength:10},{id:3,value:"Strong",minDiversity:4,minLength:12}],n="!\"#$%&'()*+,-./\\:;<=>?@[]^_`{|}~",r=(e,n=i,r)=>{n[0].minDiversity=0,n[0].minLength=0;const s=e??"",o=[{key:"lowercase",regex:"[a-z]"},{key:"uppercase",regex:"[A-Z]"},{key:"number",regex:"[0-9]"},{key:"symbol",regex:r?`[${t(r)}]`:"[^a-zA-Z0-9]"}];let a={};a.contains=o.filter((e=>new RegExp(`${e.regex}`).test(s))).map((e=>e.key)),a.length=s.length;let l=n.filter((e=>a.contains.length>=e.minDiversity)).filter((e=>a.length>=e.minLength)).sort(((e,t)=>t.id-e.id)).map((e=>({id:e.id,value:e.value})));return Object.assign(a,l[0]),a};var s={passwordStrength:r,defaultOptions:i,owaspSymbols:n};e.default=s,e.defaultOptions=i,e.owaspSymbols=n,e.passwordStrength=r,Object.defineProperty(e,"__esModule",{value:!0})})); |
{ | ||
"name": "check-password-strength", | ||
"version": "2.0.10", | ||
"version": "3.0.0", | ||
"description": "A NPM Password strength checker based from Javascript RegExp. Check passphrase if it's \"Too weak\", \"Weak\", \"Medium\" or \"Strong\"", | ||
@@ -10,3 +10,4 @@ "main": "dist/index.js", | ||
"build": "rm -rf dist && rollup -c", | ||
"test": "jest", | ||
"test": "npm run test:lib && npm run test:types", | ||
"test:lib": "vitest --disable-console-intercept", | ||
"test:types": "tsd" | ||
@@ -44,9 +45,17 @@ }, | ||
"devDependencies": { | ||
"@rollup/plugin-commonjs": "^25.0.7", | ||
"@rollup/plugin-commonjs": "^28.0.1", | ||
"@rollup/plugin-node-resolve": "^15.3.0", | ||
"@rollup/plugin-terser": "^0.4.4", | ||
"jest": "^26.4.2", | ||
"rollup": "^2.77.0", | ||
"jest": "^29.7.0", | ||
"rollup": "^4.28.0", | ||
"rollup-plugin-copy": "^3.5.0", | ||
"tsd": "^0.14.0" | ||
"tsd": "^0.31.2", | ||
"vitest": "^2.1.8" | ||
}, | ||
"tsd": { | ||
"directory": "test" | ||
}, | ||
"dependencies": { | ||
"escape-string-regexp": "^5.0.0" | ||
} | ||
} |
116
README.md
# Overview | ||
A simple way to check that password strength of a certain passphrase. A password strength checker based from [Javascript RegEx](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions). | ||
A simple way to check that password strength of a certain passphrase. The library is fully typed. | ||
@@ -23,3 +23,3 @@ [![Build status](https://dev.azure.com/dv-github-repos/check-password-strength/_apis/build/status/check-password-strength-CI)](https://dev.azure.com/dv-github-repos/check-password-strength/_build/latest?definitionId=12) | ||
```html | ||
<script src="https://unpkg.com/check-password-strength/dist/umd.js"></script> | ||
<script src="https://unpkg.com/check-password-strength/dist/umd.cjs"></script> | ||
<script type="text/javascript"> | ||
@@ -31,2 +31,3 @@ const passwordStrength = checkPasswordStrength.passwordStrength('pwd123').value; // 'Weak' | ||
## Setup & Basic Usage | ||
```javascript | ||
@@ -50,42 +51,23 @@ const { passwordStrength } = require('check-password-strength') | ||
## Additional Info | ||
## API | ||
### Object Result | ||
| Property | Desc. | | ||
| -------- | --------------------------------------------------------------- | | ||
| id | **0** = Too weak, **1** = Weak & **2** = Medium, **3** = Strong | | ||
| value | Too weak, Weak, Medium & Strong | | ||
| contains | lowercase, uppercase, symbol and/or number | | ||
| length | length of the password | | ||
### arguments | ||
### Password Length Default Options | ||
| Name | Mininum Diversity | Mininum Length | | ||
| -------- | ----------------- | -------------- | | ||
| Too weak | 0 | 0 | | ||
| Weak | 2 | 6 | | ||
| Medium | 4 | 8 | | ||
| Strong | 4 | 10 | | ||
The `passwordStrength` takes 3 arguments: | ||
```javascript | ||
console.log(passwordStrength('@Sdfasd2020!@#$')) | ||
// output | ||
{ | ||
"id": 1, | ||
"value": "Strong", | ||
"contains": ['lowercase', 'uppercase', 'symbol', 'number'], | ||
"length": 15 | ||
} | ||
``` | ||
- `password` (string): the user password | ||
- `options` (array — optional): an option to override the default complexity required to match your password policy. See below. | ||
- `restrictSymbolsTo` (string — optional): | ||
- By default, the `passwordStrength` function checks against all characters except for the 26 Latin lowercase letters, 26 uppercase letters, and 10 digits. This includes OWASP-recommended characters, accented letters, other alphabets, and emojis. | ||
- If you wish to apply restrictions, you can provide a custom string. This string should consist of unescaped symbol characters, which will be utilized internally in a RegExp expression in the following format: `[${escapeStringRegexp(restrictSymbolsTo)}]`. | ||
- Additionally, you can import and use the owaspSymbols to limit the symbols to those recommended by OWASP. | ||
### Default Options | ||
**Password Default Options** | ||
The default symbols are based from **Password Special Characters [OWASP](https://owasp.org/www-community/password-special-characters)** list (except for the space) | ||
``` | ||
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ | ||
``` | ||
Thanks for [jlherren](https://github.com/jlherren) & [Ennoriel](https://github.com/Ennoriel) for this suggestion! 👨🏻💻👨🏻💻 | ||
The default options can be required: | ||
The default options can be required: | ||
```javascript | ||
const { defaultOptions } = require("./index"); | ||
// OR | ||
import { defaultOptions } from 'check-password-strength' | ||
``` | ||
@@ -106,3 +88,3 @@ | ||
minDiversity: 2, | ||
minLength: 6 | ||
minLength: 8 | ||
}, | ||
@@ -113,3 +95,3 @@ { | ||
minDiversity: 4, | ||
minLength: 8 | ||
minLength: 10 | ||
}, | ||
@@ -120,3 +102,3 @@ { | ||
minDiversity: 4, | ||
minLength: 10 | ||
minLength: 12 | ||
} | ||
@@ -133,46 +115,19 @@ ] | ||
The `minDiversity` and `minLength` parameters of the first element cannot be overriden (set to 0 at the beginning of the method). Therefore, the first element should always correspond to a "too weak" option. | ||
**You can use an array containing fewer or more than four items to define the levels of trust.** However, the first element must have both the minDiversity and minLength parameters set to 0. This means that the first element should always represent a "too weak" option. | ||
```javascript | ||
passwordStrength('myPassword', yourCustomOptions) | ||
``` | ||
### RegEx | ||
**Strong** | ||
``` | ||
^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*"'()+,-./:;<=>?[\]^_`{|}~])(?=.{10,}) | ||
``` | ||
### Result | ||
**Medium Password RegEx used:** | ||
``` | ||
^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*"'()+,-./:;<=>?[\]^_`{|}~])(?=.{8,}) | ||
``` | ||
The result is an object containing the following values (unless you override the `options`): | ||
| RegEx | Desc. | | ||
| ----------------------------------------- | ------------------------------------------------------------------- | | ||
| ^ | The password string will start this way | | ||
| (?=.*[a-z]) | The string must contain at least 1 lowercase alphabetical character | | ||
| (?=.*[A-Z]) | The string must contain at least 1 uppercase alphabetical character | | ||
| (?=.*[0-9]) | The string must contain at least 1 numeric character | | ||
| (?=.[!"#$%&'()*+,-./:;<=>?@[\\]^_`{\|}~])) | The string must contain at least one special character | | ||
| (?=.{10,}) | The string must be eight characters or longer for Strong strength | | ||
| (?=.{8,}) | The string must be eight characters or longer for Medium strength | | ||
| (?=.{6,}) | Mininum of 6 characters for Weak strength | | ||
| Property | Desc. | | ||
| -------- | --------------------------------------------------------------- | | ||
| id | **0** = Too weak, **1** = Weak & **2** = Medium, **3** = Strong | | ||
| value | Too weak, Weak, Medium & Strong | | ||
| contains | lowercase, uppercase, number and / or symbol | | ||
| length | length of the password | | ||
## TypeScript type declarations ☑ | ||
Available starting version `v2.0.3` and above. (Thanks to [@Mesoptier!](https://github.com/Mesoptier)) | ||
If you want to translate the value (Too weak → Trop faible), you can translate it based on the return value, or override the `defaultOptions` option, which will be passed back as the function's return value. | ||
## Other resources | ||
## Contribute | ||
##### For .NET Project | ||
If you're working with .net core project, I've created a simple nuget package with same RegEx strings to validate a password strength. | ||
You can easily install via Nuget Package Manager or .NET CLI ([Check.Password.Strength](https://github.com/deanilvincent/Check.Password.Strength)). This package uses Regular Expression `new Regex()` derives from `System.Text.RegularExpressions`. You can use this especially if you want to validate the passcode strength on backend services or web apis of your project. | ||
##### Other NPM RegEx validator | ||
I also made another NPM package ([hey-regex](https://www.npmjs.com/package/hey-regex)) that checks common inputs like numbers (whole number and decimal), alpha numeric, email and url. This package only returns `true` or `false` based from the selected function (with RegEx `.test()` inside). | ||
Reference [blog](https://www.thepolyglotdeveloper.com/2015/05/use-regex-to-test-password-strength-in-javascript/). | ||
### Contribute | ||
Feel free to clone or fork this project: `https://github.com/deanilvincent/check-password-strength.git` | ||
@@ -184,5 +139,10 @@ | ||
## changelog | ||
- v3: allow all symbols by default (any character except the 26 latin lowercase, uppercase letters and 10 digits) & set the default min length to 12 instead of 10 | ||
- v2: allow configuration through `options` object | ||
- v1: first version | ||
*** | ||
Kudos to [@Ennoriel](https://github.com/Ennoriel) and his efforts for making v2.x.x possible! | ||
### License | ||
This project is licensed under the MIT License - see the [LICENSE.md](https://github.com/deanilvincent/check-password-strength/blob/master/LICENSE.md/) file for details. | ||
Kudos to [@Ennoriel](https://github.com/Ennoriel) and his efforts for making v2 and v3 possible! |
Sorry, the diff of this file is not supported yet
185
14420
1
8
141
+ Addedescape-string-regexp@^5.0.0
+ Addedescape-string-regexp@5.0.0(transitive)