const prf = new Uint8Array(prfBuffer).toHex();
const response = await fetch(`http://localhost:${location.port}`, { // Intentionally hardcoding localhost, do not broadcast anywhere else
method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ challenge, prf })
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Envpass-Challenge': challenge
+ },
+ body: JSON.stringify({ prf })
});
if (response.status === 200) {
p.textContent = 'Successfully sent passkey. You may close this window now.';
response.writeHead(400).end();
return;
}
+ if (request.headers['envpass-challenge'] !== challenge) {
+ response.writeHead(401).end();
+ return;
+ }
let body = '';
request.on('data', chunk => body += chunk);
request.on('end', () => {
const payload = JSON.parse(body);
- if (payload.challenge !== challenge) {
- response.writeHead(401).end();
- return;
- }
const prf = parsePrf(payload.prf);
if (prf === null) {
response.writeHead(400).end();
* @typedef {Object} MakePostRequestOptions
* @property {Record<string,string|null>} [headers] Headers to set on the request. Set a property to
* `null` to *delete* that header.
- * @property {string|null} [challenge] `challenge` string to pass on the request body.
* @property {string|null} [prf] `prf` string to pass on the request body.
*/
const { origin, searchParams } = new URL(url);
const {
headers = {},
- challenge = searchParams.get('challenge'),
prf = 'deadbeef000000000000000000000000000000000000000000000000cafebabe'
} = options;
const mergedHeaders = {
'Sec-Fetch-Site': 'same-origin',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Dest': 'empty',
+ 'Envpass-Challenge': searchParams.get('challenge'),
...headers
}
const filteredHeaders = filterNullValues(mergedHeaders);
- const body = filterNullValues({ challenge, prf });
+ const body = filterNullValues({ prf });
return new Request(origin, {
method: 'POST',
headers: filteredHeaders,
// See https://github.com/nodejs/undici/issues/1305
const { url } = await setupServer(t);
const { origin, searchParams } = new URL(url);
- const challenge = searchParams.get('challenge');
const prf = 'deadbeef000000000000000000000000000000000000000000000000cafebabe';
const options = {
method: 'POST',
'Content-Type': 'application/json',
'Origin': origin,
'Sec-Fetch-Site': 'same-origin',
- 'Sec-Fetch-Dest': 'empty'
+ 'Sec-Fetch-Dest': 'empty',
+ 'Envpass-Challenge': searchParams.get('challenge')
}),
- body: JSON.stringify({ challenge, prf })
+ body: JSON.stringify({ prf })
}
deepStrictEqual((await request(origin, options)).statusCode, 403); // Tests the unset case
options.headers['Sec-Fetch-Mode'] = 'navigate';
deepStrictEqual((await fetch(makePostRequest(url, { headers: { 'Content-Type': null } }))).status, 400);
deepStrictEqual((await fetch(makePostRequest(url, { headers: { 'Content-Type': 'INVALID' } }))).status, 400);
});
- test('validates challenge on POST', async (t) => {
+ test('validates Envpass-Challenge header on POST', async (t) => {
const { url } = await setupServer(t);
- deepStrictEqual((await fetch(makePostRequest(url, { challenge: null }))).status, 401);
- deepStrictEqual((await fetch(makePostRequest(url, { challenge: 'INVALID' }))).status, 401);
+ deepStrictEqual((await fetch(makePostRequest(url, { headers: { 'Envpass-Challenge': null } }))).status, 401);
+ deepStrictEqual((await fetch(makePostRequest(url, { headers: { 'Envpass-Challenge': 'INVALID' } }))).status, 401);
});
test('validates prf on POST', async (t) => {
const { url } = await setupServer(t);