(Prefer traditional serverless sorcery? See the AWS Lambda version here)
Deploy a private, secure and serverless RESTful endpoint for sanely scoring users' new passwords using Dropbox's zxcvbn
library while (k-)anonymously querying Troy Hunt's haveibeenpwned
collection of +10 billion breached accounts.
Example: handling results with VuetifyJS
People seemed to think this concept was neat, and a tiny RESTful API like this is a perfect use case for Cloudflare Workers.
As a bonus, over 90% of pwnedpassword
queries are already cached on Cloudflare's edge, making response times spooky fast 👻
- Rename
example.cloudflare.env
tocloudflare.env
and edit the configuration as needed. - Install deps with
npm install
- Launch 🚀 with
npm run deploy
The following options are configurable via cloudflare.env
:
-
ROUTE_PATTERN
: Optionally include a route-matching pattern for your worker. Seeexample.cloudflare.env
for details on how patterns are parsed and applied (default:undefined
) -
ALLOWED_ORIGIN
: Whitelisted origin for Cross Origin Resource Sharing. If not provided, all origins are allowed (default:*
) -
ALLOWED_ORIGIN_PATTERNS
: Comma-seperated list of strings to be converted toRegExp
patterns for testing the incoming request origin. If the origin matches, it's returned as allowed. If no pattern is matched, CORS falls back to the configuredALLOWED_ORIGIN
(default:undefined
)- Example:
"(foo|bar|buzz)\.example\.lol,yet\.another\.example\.omg"
- Example:
-
CORS_MAXAGE
: Value in seconds for theAccess-Control-Max-Age
CORS header (default:"300"
) -
ALWAYS_RETURN_SCORE
: Return thezxcvbn
score even if thepwnedpasswords
match value is > 0. See Response for details (default:undefined
, therebyfalse
) -
CUSTOM_PW_DICT
: Comma-seperated list of words/phrases to be included in thezxcvbn
strength estimation dictionary. It's a good idea to include e.g. your company or application name here (default:''
) -
RETURN_PW_METADATA
: Return the full result of thezxcvbn
strength estimation as ametadata
response key. Refer to the zxcvbn documentation for details on what that includes (default:undefined
, therebyfalse
)
Update configuration à la changes to cloudflare.env
by re-running npm run deploy
.
NOTE: For reasons unknown, the Cloudflare Dash may continue to show older scripts after a successful upload. Check the x-worker-last-modified
response header to verify that your latest script is up and running.
POST user password input to your route as JSON with field password
like so:
// pwned password
{
"password": "monkey123"
}
// stronger password
{
"password": "wonderful waffles"
}
Our little worker-bro will reply with an appropriate status code, and JSON body with ok
indicating successful scoring and range search, a strength estimation score
of 0 through 4 per zxcvbn
, and pwned
matches, indicating the number times the input appears in the haveibeenpwned
database.
// pwned password 'monkey123'
{
"ok": true,
"score": 0,
"pwned": 56491
}
// stronger password 'wonderful waffles'
{
"ok": true,
"score": 3,
"pwned": 0
}
By default, if pwned
is greater than 0, then score
will always be 0. You can override this behavior by settings "ALWAYS_RETURN_SCORE"
to true
in cloudflare.env
If RETURN_PW_METADATA
is truthy, responses will also include a metadata
key with the complete zxcvbn
strength estimation result object.
Each response will also contain a x-worker-last-modified
header with a timestamp indicating when the script was built and deployed.
Failure will return JSON to inform you that something's not ok
and a message
as to why.
{
"ok": false,
"message": "It went kaput 💩"
}
Send a GET
request to act as a little health-check. Response 204
means you're good to go. Useful for testing CORS configuration 👍
I am not affiliated with Cloudflare, Troy Hunt, Dropbox, haveibeenpwned, good software development in general, or any combination thereof.
Handling user passwords is no laughing matter, so handle them with care and respect.
Just like your own users, assume that I have no idea what I'm doing. This part is important, because I have no idea what I'm doing.
REVIEW THE SOURCE, and use at your own risk 🙈
MIT