feat: add authentication [sls] (#276)

* feat: add authentication for alchemy notify in the mint handler.

* feat: add verifyURL to the app handlers.

* feat: fix the alchemy signature typo, change the auth function of app handler to use a front-end signing key, remove unnecessary logs from build handler.

---------

Co-authored-by: Nima Rasooli <nimarasooli1@gmail.com>
This commit is contained in:
Shredder 2023-06-16 17:49:47 +03:30 committed by GitHub
parent 665fdd4940
commit 948f926c92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 10 deletions

View File

@ -9,6 +9,24 @@ import {
CreatePullZoneMethodArgs,
LoadFreeCertificateMethodArgs,
} from '@libs/bunnyCDN';
import * as crypto from "crypto";
function isTheSignatureValid(
body: string, // must be raw string body, not json transformed version of the body
signature: string, // the "lambda-signature" from header
signingKey: string, // signing secret key for front-end
) {
const hmac = crypto.createHmac("sha256", signingKey); // Create a HMAC SHA256 hash using the signing key
hmac.update(body, "utf8"); // Update the token hash with the request body using utf8
const digest = hmac.digest("hex");
if (signature !== digest) {
// the request is not valid
return formatJSONResponse({
status: 401,
message: 'Unauthorized',
});
}
}
export const verifyApp = async (
event: APIGatewayEvent
@ -23,6 +41,13 @@ export const verifyApp = async (
});
}
// Check the lambda-signature and confirm the value of the FE_SIGNING_KEY env variable.
// If both are valid, verify the authenticity of the request.
if (event.headers["lambda-signature"] === undefined) throw Error("Header field 'lambda-signature' was not found.");
if (process.env.FE_SIGNING_KEY === undefined) throw Error("FE_SIGNING_KEY env variable not found.");
else { isTheSignatureValid(event.body, event.headers["lambda-signature"], process.env.FE_SIGNING_KEY); };
// Set up constants
const bunnyCdn = new BunnyCdn(process.env.BUNNY_CDN_ACCESS_KEY);
const hostname = JSON.parse(event.body).hostname;
@ -50,13 +75,20 @@ export const submitAppInfo = async (
try {
// Check the parameters and environment variables
dotenv.config();
if (event.body === null || process.env.BUNNY_CDN_ACCESS_KEY == undefined) {
if (event.body === null || process.env.BUNNY_CDN_ACCESS_KEY == undefined || event.headers.originUrl === undefined) {
return formatJSONResponse({
status: 422,
message: 'Required parameters were not passed.',
});
}
// Check the lambda-signature and confirm the value of the FE_SIGNING_KEY env variable.
// If both are valid, verify the authenticity of the request.
if (event.headers["lambda-signature"] === undefined) throw Error("Header field 'lambda-signature' was not found.");
if (process.env.FE_SIGNING_KEY === undefined) throw Error("FE_SIGNING_KEY env variable not found.");
else { isTheSignatureValid(event.body, event.headers["lambda-signature"], process.env.FE_SIGNING_KEY); };
// Set up constants
const bunnyCdn = new BunnyCdn(process.env.BUNNY_CDN_ACCESS_KEY);
const data = JSON.parse(event.body);

View File

@ -27,7 +27,6 @@ export const submitBuildInfo = async (
domain: data.domain,
verificationTransactionHash: 'Not verified.',
};
console.log(buildInfo);
// Add build record to the database, if it's not already added
const buildRecord = await prisma.builds.findMany({
@ -38,11 +37,9 @@ export const submitBuildInfo = async (
domain: buildInfo.domain,
},
});
console.log(buildRecord);
if (buildRecord.length == 0) {
console.log('here i am');
await prisma.builds.create({
data: {

View File

@ -7,6 +7,25 @@ import { formatJSONResponse } from '@libs/api-gateway';
import { v4 } from 'uuid';
import { initPrisma, prisma } from '@libs/prisma';
import { contractInstance, web3 } from '@libs/nfa-contract';
import * as crypto from "crypto";
function isTheSignatureValid(
body: string, // must be raw string body, not json transformed version of the body
signature: string, // the "x-alchemy-signature" from header
signingKey: string, // taken from dashboard for specific webhook
) {
const hmac = crypto.createHmac("sha256", signingKey); // Create a HMAC SHA256 hash using the signing key
hmac.update(body, "utf8"); // Update the token hash with the request body using utf8
const digest = hmac.digest("hex");
if (signature !== digest) {
// the request is not valid
return formatJSONResponse({
status: 401,
message: 'Unauthorized',
});
}
}
export const submitMintInfo = async (
event: APIGatewayEvent
///context: APIGatewayEventRequestContext
@ -19,10 +38,14 @@ export const submitMintInfo = async (
});
}
// Check the alchemy signature and confirm the value of the ALCHEMY_SIGNING_KEY env variable.
// If both are valid, verify the authenticity of the request.
if (event.headers["x-alchemy-signature"] === undefined) throw Error("Header field 'x-alchemy-signature' was not found.");
if (process.env.ALCHEMY_SIGNING_KEY === undefined) throw Error("ALCHEMY_SIGNING_KEY env variable not found.");
else { isTheSignatureValid(event.body, event.headers["x-alchemy-signature"], process.env.ALCHEMY_SIGNING_KEY); };
const id = v4();
/**if (!verifyAlchemySig(event.headers.xalchemywork)) {
throw new Error('Invalid sig');
}**/
const eventBody = JSON.parse(event.body);
const topics = eventBody.event.data.block.logs[1].topics.slice(1, 4);