Skip to content

Commit

Permalink
Fix url and secret key; move to a single file
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanlee85 committed Jan 9, 2024
1 parent 78bb863 commit 9576505
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 119 deletions.
103 changes: 103 additions & 0 deletions examples/v7-edge-functions/functions/general/signed-request/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { URL } from 'whatwg-url';
import HmacSHA1 from 'crypto-js/hmac-sha1';
import Base64 from 'crypto-js/enc-base64';
import createFetchForOrigin from '../../../utils/createFetchForOrigin';

const fetch = createFetchForOrigin('echo');

export async function handleHttpRequest(request, context) {
// ** IMPORTANT **
// Secret key should be defined as an environment variable in the Edgio console
const secretKey = '$0m3th!ngS3cr3t'; // context.environmentVars.REQ_SIGNING_SECRET_KEY;

if (request.url.includes('/sign/')) {
return generateSignedUrl(request, secretKey);
}

return verifyAndFetch(request, secretKey);
}

/**
* Generates a signed URL for the given URL and secret key
* @param {URL} url
* @param {string} secretKey
*/
async function generateSignedUrl(request, key) {
const url = new URL(request.url);

// Replace /sign/ with /verify/ in the URL since we are generating a signed URL for verification
url.pathname = url.pathname.replace('/sign/', '/verify/');

const expirationMs = 1000 * 60 * 5; // 5 minutes
const expiry = Date.now() + expirationMs;
const dataToAuthenticate = url.pathname + expiry;

const hash = HmacSHA1(dataToAuthenticate, key);
const base64Mac = Base64.stringify(hash);

url.searchParams.set('mac', base64Mac);
url.searchParams.set('expiry', expiry.toString());

const validUrl = url.toString();
const modifiedExpiryUrl = new URL(validUrl);
modifiedExpiryUrl.searchParams.set('expiry', `${expiry + 5}`);
const modifiedMacUrl = new URL(validUrl);
modifiedMacUrl.searchParams.set('mac', `${base64Mac}x`);

console.log('Valid URL:\n', validUrl);
console.log('Modified expiry URL:\n', modifiedExpiryUrl.toString());
console.log('Modified MAC URL:\n', modifiedMacUrl.toString());

const htmlResponse = `
<html>
<body>
<p>Click the following links for verification:</p>
<ul>
<li><a href="${validUrl}">Valid URL</a><pre>(${validUrl})</pre></li>
<li><a href="${modifiedExpiryUrl}">Invalid with modified Expiry URL</a><pre>(${modifiedExpiryUrl})</pre></li>
<li><a href="${modifiedMacUrl}">Invalid with modified Mac URL</a><pre>(${modifiedMacUrl})</pre></li>
</ul>
</body>
</html>
`;

return new Response(htmlResponse, {
headers: { 'Content-Type': 'text/html' },
});
}

/**
* Verifies the MAC and expiry of the given URL. If the URL is valid, the request is forwarded to the origin.
*/
async function verifyAndFetch(request, key) {
const invalidResponse = new Response('Invalid request', { status: 403 });
const url = new URL(request.url);

if (!url.searchParams.has('mac') || !url.searchParams.has('expiry')) {
return invalidResponse;
}

const expiry = Number(url.searchParams.get('expiry'));
const dataToAuthenticate = url.pathname + expiry;

const receivedMacBase64 = url.searchParams.get('mac');
const receivedMac = Base64.parse(receivedMacBase64);

const hash = HmacSHA1(dataToAuthenticate, key);
const hashInBase64 = Base64.stringify(hash);

// Ensure that the MAC is valid
if (hashInBase64 !== receivedMacBase64) {
return invalidResponse;
}

// Ensure that the URL has not expired
if (Date.now() > expiry) {
return invalidResponse;
}

// Forward the remaining request path after **/verify/* to the origin
url.pathname = url.pathname.split('/verify/')[1];

return fetch(url.toString());
}

This file was deleted.

This file was deleted.

7 changes: 2 additions & 5 deletions examples/v7-edge-functions/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,8 @@ export default new Router()
edge_function: './functions/general/security-response-headers.js',
})
// request signing
.match('/example/signed-request/verify/:path*', {
edge_function: './functions/general/signed-request/verify.js',
})
.match('/example/signed-request/sign/:path*', {
edge_function: './functions/general/signed-request/sign.js',
.match(/\/example\/signed-request\/(sign|verify)\/(.*)/, {
edge_function: './functions/general/signed-request/main.js',
})
.match('/example/caching', {
caching: {
Expand Down

0 comments on commit 9576505

Please sign in to comment.