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:
parent
665fdd4940
commit
948f926c92
|
|
@ -9,6 +9,24 @@ import {
|
||||||
CreatePullZoneMethodArgs,
|
CreatePullZoneMethodArgs,
|
||||||
LoadFreeCertificateMethodArgs,
|
LoadFreeCertificateMethodArgs,
|
||||||
} from '@libs/bunnyCDN';
|
} 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 (
|
export const verifyApp = async (
|
||||||
event: APIGatewayEvent
|
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
|
// Set up constants
|
||||||
const bunnyCdn = new BunnyCdn(process.env.BUNNY_CDN_ACCESS_KEY);
|
const bunnyCdn = new BunnyCdn(process.env.BUNNY_CDN_ACCESS_KEY);
|
||||||
const hostname = JSON.parse(event.body).hostname;
|
const hostname = JSON.parse(event.body).hostname;
|
||||||
|
|
@ -50,13 +75,20 @@ export const submitAppInfo = async (
|
||||||
try {
|
try {
|
||||||
// Check the parameters and environment variables
|
// Check the parameters and environment variables
|
||||||
dotenv.config();
|
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({
|
return formatJSONResponse({
|
||||||
status: 422,
|
status: 422,
|
||||||
message: 'Required parameters were not passed.',
|
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
|
// Set up constants
|
||||||
const bunnyCdn = new BunnyCdn(process.env.BUNNY_CDN_ACCESS_KEY);
|
const bunnyCdn = new BunnyCdn(process.env.BUNNY_CDN_ACCESS_KEY);
|
||||||
const data = JSON.parse(event.body);
|
const data = JSON.parse(event.body);
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ export const submitBuildInfo = async (
|
||||||
domain: data.domain,
|
domain: data.domain,
|
||||||
verificationTransactionHash: 'Not verified.',
|
verificationTransactionHash: 'Not verified.',
|
||||||
};
|
};
|
||||||
console.log(buildInfo);
|
|
||||||
|
|
||||||
// Add build record to the database, if it's not already added
|
// Add build record to the database, if it's not already added
|
||||||
const buildRecord = await prisma.builds.findMany({
|
const buildRecord = await prisma.builds.findMany({
|
||||||
|
|
@ -38,11 +37,9 @@ export const submitBuildInfo = async (
|
||||||
domain: buildInfo.domain,
|
domain: buildInfo.domain,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
console.log(buildRecord);
|
|
||||||
|
|
||||||
|
|
||||||
if (buildRecord.length == 0) {
|
if (buildRecord.length == 0) {
|
||||||
console.log('here i am');
|
|
||||||
|
|
||||||
await prisma.builds.create({
|
await prisma.builds.create({
|
||||||
data: {
|
data: {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,25 @@ import { formatJSONResponse } from '@libs/api-gateway';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
import { initPrisma, prisma } from '@libs/prisma';
|
import { initPrisma, prisma } from '@libs/prisma';
|
||||||
import { contractInstance, web3 } from '@libs/nfa-contract';
|
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 (
|
export const submitMintInfo = async (
|
||||||
event: APIGatewayEvent
|
event: APIGatewayEvent
|
||||||
///context: APIGatewayEventRequestContext
|
///context: APIGatewayEventRequestContext
|
||||||
|
|
@ -18,12 +37,16 @@ export const submitMintInfo = async (
|
||||||
message: 'Required parameters were not passed.',
|
message: 'Required parameters were not passed.',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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();
|
const id = v4();
|
||||||
/**if (!verifyAlchemySig(event.headers.xalchemywork)) {
|
|
||||||
throw new Error('Invalid sig');
|
|
||||||
}**/
|
|
||||||
|
|
||||||
const eventBody = JSON.parse(event.body);
|
const eventBody = JSON.parse(event.body);
|
||||||
const topics = eventBody.event.data.block.logs[1].topics.slice(1, 4);
|
const topics = eventBody.event.data.block.logs[1].topics.slice(1, 4);
|
||||||
const hexCalldata = eventBody.event.data.block.logs[1].data;
|
const hexCalldata = eventBody.event.data.block.logs[1].data;
|
||||||
|
|
@ -129,9 +152,9 @@ export const submitMintInfo = async (
|
||||||
domain: decodedLogs.externalURL,
|
domain: decodedLogs.externalURL,
|
||||||
verificationTransactionHash: 'Not verified'
|
verificationTransactionHash: 'Not verified'
|
||||||
};
|
};
|
||||||
|
|
||||||
initPrisma();
|
initPrisma();
|
||||||
|
|
||||||
// Check if there is any build associated with the repository, commit hash, tokenId, and ipfsHash
|
// Check if there is any build associated with the repository, commit hash, tokenId, and ipfsHash
|
||||||
|
|
||||||
const build = await prisma.builds.findMany({
|
const build = await prisma.builds.findMany({
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue