-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix url and secret key; move to a single file
- Loading branch information
1 parent
78bb863
commit 9576505
Showing
4 changed files
with
105 additions
and
119 deletions.
There are no files selected for viewing
103 changes: 103 additions & 0 deletions
103
examples/v7-edge-functions/functions/general/signed-request/main.js
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
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()); | ||
} |
54 changes: 0 additions & 54 deletions
54
examples/v7-edge-functions/functions/general/signed-request/sign.js
This file was deleted.
Oops, something went wrong.
60 changes: 0 additions & 60 deletions
60
examples/v7-edge-functions/functions/general/signed-request/verify.js
This file was deleted.
Oops, something went wrong.
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