Gathering detailed insights and metrics for aws4-express
Gathering detailed insights and metrics for aws4-express
Express middleware handlers for validation AWS Signature V4. Your web app can mimic AWS services, and you can use benefit from already well-defined standard to securing web API.
npm install aws4-express
Typescript
Module System
Node Version
NPM Version
72.3
Supply Chain
95.5
Quality
77.7
Maintenance
100
Vulnerability
99.5
License
TypeScript (87.22%)
JavaScript (12.78%)
Love this project? Help keep it running — sponsor us today! 🚀
Total Downloads
34,325
Last Day
88
Last Week
379
Last Month
1,499
Last Year
24,788
MIT License
1 Stars
66 Commits
1 Forks
1 Watchers
1 Branches
1 Contributors
Updated on Dec 11, 2024
Minified
Minified + Gzipped
Latest Version
0.10.2
Package Id
aws4-express@0.10.2
Unpacked Size
138.31 kB
Size
29.12 kB
File Count
46
NPM Version
10.8.2
Node Version
20.18.1
Published on
Dec 11, 2024
Cumulative downloads
Total Downloads
Last Day
175%
88
Compared to previous day
Last Week
10.5%
379
Compared to previous week
Last Month
-0.1%
1,499
Compared to previous month
Last Year
161.1%
24,788
Compared to previous year
1
24
This library is about to create on security layer of your API using well defined comunication standard known as AWS Signature V4.
We provide Express middleware handler awsVerify
for validation your AWS Signature V4
with your access and secret pair of key. So, your web app can mimic AWS services, and you can use benefits from already well-defined standard to securing your web API.
At this moment, library is based on general version of aws4 signature: Authenticating Requests (AWS Signature Version 4)
Until we hit >=1.x.x, there could be possible breaking changes on minor changes. Use at least 0.8.0 version.
1npm install aws4-express
There are prepared helpers to handle the original body with any changes, because if you change a single character, your request won't be valid anymore.
If you use express parsers like express.raw()
or express.json()
or express.urlencoded
you can attach with handler rawBodyFromVerify
. You can also write own stream parser or use our rawBodyFromStream
.
1 import express from 'express'; 2 import { awsVerify, rawBodyFromVerify, rawBodyFromStream } from 'aws4-express'; 3 4 const app = express(); 5 // whenever you may need to get original body string and you case 6 // when json parser u may use like this 7 app.use( 8 express.json({ 9 type: '*/*', 10 verify: rawBodyFromVerify, 11 }), 12 ); 13 14 // or when json parser u may use like this 15 app.use( 16 express.raw({ 17 type: '*/*', 18 verify: rawBodyFromVerify, 19 }) 20 ); 21 22 // or when url encoded body u may use like this 23 app.use( 24 express.urlencoded({ 25 extended: true, 26 type: '*/*', 27 verify: rawBodyFromVerify, 28 }), 29 ); 30 31 // or events on when json parser u may use like this 32 app.use(rawBodyFromStream); 33 34 // main handler to authorization incomming requests: 35 app.use(awsVerify({ 36 secretKey: (message, req, res, next) => { 37 // fetch secret key from your storage key/secret pairs (sql, nosql, memory) 38 // you have to provide your own secret provider here. 39 // retrun string | undefined 40 41 return getMySecretByKey(message.accessKey), 42 } 43 })); 44 45 // your routers ... 46 app.all('*', ...); 47 app.get('/get', ...); 48 app.post('/post', ...); 49 50 return app;
authorization
- [required] must have in proper format: Authorization: AWS4-HMAC-SHA256
Credential=ACCESS_KEY
/DATE
/REGION
/SERVICE
/TYPE_REQUEST
,
SignedHeaders=< SIGNED_HEADERS>,
Signature=SIGNATURE
:
ACCESS_KEY
- any text without whitespaces and slashes (/) - Only have to do is handle distribution of access_key, secret_key and these keys have to be accessible on the server side.DATE
- is part of X-AMZ-DATE: in format YYYYMMDD.REGION
- any thing you need in this place or use something from amz regions.SERVICE
- any thing you need in this place or 'execute-api' for sake of simplicity.TYPE_REQUEST
- you can use your variations instead of standard 'aws4_request'.SIGNED_HEADERS
- all signed headers - more headers mean harder to temper request. Required headers at this moment: host:x-amz-dateSIGNATURE
- calculated signature based on Authenticating Requests (AWS Signature Version 4)x-amz-date
- [required] must have in request to valid request signaturex-amz-content-sha256
- [optional] you can attach precalculated hash. When X-Amz-Content-Sha256 is sent we skip calculating hash from body. This way is less secure and recommended use at least with X-Amz-Expires
.
onBeforeParse
or onAfterParse
.UNSIGNED-PAYLOAD
instead of sha-256 signature - this cloud speed up your bigger request, but signature will be same as long as headers remain same.crypto.createHash('sha256').update(data, 'utf8').digest('hex')
x-amz-expires
- [optional] - format: YYYY-mm-ddTHH:MM:SS
. If you want valid your request for a period of time and don't want to reuse signature when time is up.Pull Requests are welcome.
The awsVerify
function is an Express.js middleware that verifies AWS signatures in incoming requests.
1import { awsVerify } from 'aws4-express'; 2 3app.use(awsVerify(options));
options
: An object of type AwsVerifyOptions
Returns an Express.js middleware function.
The AwsVerifyOptions
object can contain the following fields:
(message: AwsIncomingMessage, req: Request, res: Response, next: NextFunction) => Promise<string | undefined> | string | undefined
undefined
if the key is not available.(headers: Dictionary) => Promise<Dictionary> | Dictionary
(req: Request) => Promise<boolean> | boolean
false
, validation will be skipped.(req: Request, res: Response, next: NextFunction) => Promise<void> | void
(req: Request, res: Response, next: NextFunction) => Promise<void> | void
(req: Request, res: Response, next: NextFunction) => Promise<void> | void
(req: Request, res: Response, next: NextFunction) => Promise<boolean> | boolean
false
, validation will be stopped.true
.(message: AwsIncomingMessage, req: Request, res: Response, next: NextFunction) => Promise<boolean> | boolean
false
, validation will be stopped.true
.(message: AwsIncomingMessage | undefined, req: Request, res: Response, next: NextFunction) => Promise<void> | void
next()
.1import express from 'express'; 2import { awsVerify, rawBodyFromVerify } from 'aws4-express'; 3 4const app = express(); 5 6app.use(express.json({ type: '*/*', verify: rawBodyFromVerify })); 7 8app.use(awsVerify({ 9 secretKey: async (message) => { 10 // Implement secret key retrieval logic 11 return 'your_secret_key'; 12 }, 13 onSignatureMismatch: (req, res) => { 14 res.status(403).send('Unauthorized'); 15 } 16})); 17 18app.get('/', (req, res) => { 19 res.send('Hello, AWS-verified world!'); 20}); 21 22app.listen(3000, () => { 23 console.log('Server is running on port 3000'); 24});
In this example, the awsVerify
middleware is used to verify the AWS signature for all incoming requests. A custom secretKey
function is used to provide the secret key, and onSignatureMismatch
defines a custom response for signature mismatch cases.
awsVerify
:1express.use(awsVerify({ 2 secretKey: (message: AwsIncomingMessage, req: Request, res: Response, next: NextFunction) => Promise<string | undefined> | string | undefined; 3 headers?: (headers: Dictionary) => Promise<Dictionary> | Dictionary; 4 enabled?: (req: Request) => Promise<boolean> | boolean; 5 onMissingHeaders?: (req: Request, res: Response, next: NextFunction) => Promise<void> | void; 6 onSignatureMismatch?: (req: Request, res: Response, next: NextFunction) => Promise<void> | void; 7 onExpired?: (req: Request, res: Response, next: NextFunction) => Promise<void> | void; 8 onBeforeParse?: (req: Request, res: Response, next: NextFunction) => Promise<boolean> | boolean; 9 onAfterParse?: ( 10 message: AwsIncomingMessage, 11 req: Request, 12 res: Response, 13 next: NextFunction, 14 ) => Promise<boolean> | boolean; 15 onSuccess?: ( 16 message: AwsIncomingMessage | undefined, 17 req: Request, 18 res: Response, 19 next: NextFunction, 20 ) => Promise<void> | void; 21}))
awsVerify
:1 { 2 enabled: () => true, 3 headers: (req) => req.headers, 4 onExpired: (res) => { 5 res.status(401).send('Request is expired'); 6 }, 7 onMissingHeaders: (res) => { 8 res.status(400).send('Required headers are missing'); 9 }, 10 onSignatureMismatch: (res) => { 11 res.status(401).send('The signature does not match'); 12 }, 13 onBeforeParse: () => true, 14 onAfterParse: () => true, 15 onSuccess: () => next() 16 }
No vulnerabilities found.
No security vulnerabilities found.