UNPKG

@filen/aws4-express

Version:

Express middleware handlers for validation AWS Signature V4

106 lines (97 loc) 3.06 kB
import http from 'http'; import express, { NextFunction, Request, Response } from 'express'; import request from 'supertest'; import { sign, Request as Aws4Request, Credentials as Aws4Credentials } from 'aws4'; import { awsVerify, AwsVerifyOptions, rawBodyFromStream, rawBodyFromVerify } from '../..'; export const methods = ['get', 'post', 'put', 'delete'] as const; export type MethodTypes = (typeof methods)[number]; export const parsers = ['json', 'urlencoded', 'raw', 'custom', 'none'] as const; export type ParserTypes = (typeof parsers)[number]; export interface ExpressAppOptions { parser: ParserTypes; path: string; testRouter: (req: Request, res: Response, next: NextFunction) => void; } const expressApp = (optionsAwsVerify: AwsVerifyOptions, optionsExpress: ExpressAppOptions) => { const routePath = optionsExpress.path.substring(0, optionsExpress.path.indexOf('?')) ?? '/'; const app = express(); switch (optionsExpress.parser) { case 'json': { app.use( express.json({ type: '*/*', verify: rawBodyFromVerify, }), ); break; } case 'urlencoded': { app.use( express.urlencoded({ extended: true, type: '*/*', verify: rawBodyFromVerify, }), ); break; } case 'raw': { app.use( express.raw({ type: '*/*', verify: rawBodyFromVerify, }), ); break; } case 'none': { break; } case 'custom': { app.use(rawBodyFromStream); break; } default: { throw new Error('Parser not implemented'); } } app.use(awsVerify(optionsAwsVerify)); app.all(routePath, optionsExpress.testRouter); return app; }; export const sendSignedRequest = async ( optionsAwsVerify: AwsVerifyOptions, optionsAwsSigned: Aws4Request, optionsExpress: Partial<ExpressAppOptions>, aws4Credentials: Aws4Credentials, expectedHttpCode: number, afterSignedRequest?: Aws4Request, afterAuthorizationSignature?: string, ) => { const signedRequest = sign(optionsAwsSigned, aws4Credentials); const modifiedRequest = { ...signedRequest, ...afterSignedRequest, headers: { ...signedRequest.headers, ...afterSignedRequest?.headers, ['Authorization']: afterAuthorizationSignature ?? signedRequest.headers?.Authorization, } as http.IncomingHttpHeaders, }; const method = optionsAwsSigned.method?.toLowerCase() ?? 'NOT IMPLEMENTED'; await request( expressApp(optionsAwsVerify, { parser: 'json', path: optionsAwsSigned.path ?? '/', testRouter: (req, res, _next) => { res.send(req.query); }, ...optionsExpress, }), ) [method as MethodTypes](optionsAwsSigned.path ?? '/') .set(modifiedRequest.headers ?? {}) .send(optionsAwsSigned.body) .expect(expectedHttpCode); return modifiedRequest.headers?.Authorization; };