Created
February 24, 2018 16:36
-
-
Save jgrahamc/21f31c8fb4b2c27bda4f605197d5143f to your computer and use it in GitHub Desktop.
Cloudflare Workers that adds an "Cf-Password-Pwnd" header to a POST request indicating whether the 'password' field appears in Troy Hunt's database of pwned passwords.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
addEventListener('fetch', event => { | |
event.respondWith(fetchAndCheckPassword(event.request)) | |
}) | |
async function fetchAndCheckPassword(req) { | |
if (req.method == "POST") { | |
try { | |
const post = await req.formData(); | |
const pwd = post.get('password') | |
const enc = new TextEncoder("utf-8").encode(pwd) | |
let hash = await crypto.subtle.digest("SHA-1", enc) | |
let hashStr = hex(hash).toUpperCase() | |
const prefix = hashStr.substring(0, 5) | |
const suffix = hashStr.substring(5) | |
const pwndpwds = await fetch('https://api.pwnedpasswords.com/range/' + prefix) | |
const t = await pwndpwds.text() | |
const pwnd = t.includes(suffix) | |
let newHdrs = new Headers(req.headers) | |
newHdrs.set('Cf-Password-Pwnd', pwnd?'YES':'NO') | |
const init = { | |
method: 'POST', | |
headers: newHdrs, | |
body: post | |
} | |
return await fetch(req.url, init) | |
} catch (err) { | |
return new Response('Internal Error') | |
} | |
} | |
return await fetch(req) | |
} | |
function hex(a) { | |
var h = ""; | |
var b = new Uint8Array(a); | |
for(var i = 0; i < b.length; i++){ | |
var hi = b[i].toString(16); | |
h += hi.length === 1?"0"+hi:hi; | |
} | |
return h; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
So, I had previously commented here that you should change:
to:
By passing a whole
Request
object as the first parameter, rather than just a URL, you make sure to copy all of the properties of the original request -- except for the ones that are overridden byinit
, of ocurse. This is important, for example, because you want to make sure to use the same redirect mode (thereq.redirect
property). This script as written currently will unfortunately cause POST redirects to be handled at the worker level rather than returned to the client (because the default redirect mode is "follow", but for incoming proxied requests it's "manual").However, this correction doesn't work! This code will throw an exception complaining that
req.body
is already used. Butinit
is providing a new body, so this shouldn't matter.This appears to be a bug in the Fetch API spec (not just our implementation). We've filed: whatwg/fetch#674