I'm a freelance backend developer & french blogger
- À la découverte de…AdonisJS
- Clarifiez les décisions techniques avec les ADRs
- TypeScript : Programmation de types
- Logging Node.js avec Pino
- Docker : conteneuriser son application
Express/Restify middleware to authenticate HTTP requests based on api key and signature.
License: MIT License
I'm a freelance backend developer & french blogger
This looks like exactly what I need for securing my simple API, however, the example usage makes it seem like I can easily set an API key, pass that as a Bearer token and be done with it, however, I'm starting to suspect that the HTTP signature signing is not optional. Is this correct? If so, why isn't that part of the example?
In the parser.js line 101 shouldn't the new line character be escaped?
Something like
signatureParams.signingString += '\\n';
Without this I am always getting Bad signature for multiple headers. Everything works okay for 1 header
Hi,
I nearly tried 1000 different ways of generating the signature. Search nearly half a day to figure out, what the heck is going on. I used the Host URL as host, the receiver URL as host. Without host, with and without "(request-target)". Tried date header only. without any headers. Always the same result: BadSignatureError: Bad signature.
Can u please help out? What am I doing wrong?
await axios
.post(`http://localhost:xxxx/what/is/going/on`, postData, {
headers: {
'Date': signingDate,
'Authorization': getApiKeyAuthHeader(
{
url: '/what/is/going/on',
method: 'post',
},
'XXX',
'XXX-secret'
)
}
})
// [...]
import CryptoJS = require('crypto-js');
export function getApiKeyAuthHeader(data: {
method: 'post' | 'get' | 'put' | 'patch' | 'delete',
url: string
},
apiKey,
apiSecretKey) {
const signatureRawData = `(request-target): ${data.method} ${data.url}`
const signature = CryptoJS.enc.Utf8.parse(signatureRawData);
const signatureBytes = CryptoJS.HmacSHA256(signature, apiSecretKey);
const requestSignatureBase64String = CryptoJS.enc.Base64.stringify(signatureBytes);
return `Signature keyId="${apiKey}",algorithm="hmac-sha256",headers="(request-target)",signature="${requestSignatureBase64String}"`;
}
Console output on receiver side:
::ffff:127.0.0.1 - - [09/Sep/2021:20:48:02 +0000] "POST /what/is/going/on HTTP/1.1" 500 60 "-" "axios/0.21.4"
{
accept: 'application/json, text/plain, */*',
'content-type': 'application/json',
date: 'Thu, 09 Sep 2021 20:57:25 GMT',
authorization: 'Signature keyId="XXX",algorithm="hmac-sha256",headers="(request-target)",signature="0YaPbz9lAJ3trsJvWSRwCxTAf7h7/1NGSdK/5jY20Fw="',
'user-agent': 'axios/0.21.4',
'content-length': '2',
host: 'localhost:xxxx',
connection: 'close'
}
BadSignatureError: Bad signature.
- index.js?:57 eval
[.]/[api-key-auth]/lib/index.js?:57:21
- app.ts?:158 getSecret
webpack://express/./app/app.ts?:158:16
- index.js?:49 middleware
[.]/[api-key-auth]/lib/index.js?:49:5
- app.ts?:170 authCheck
webpack://express/./app/app.ts?:170:41
- app.ts?:147 eval
webpack://express/./app/app.ts?:147:5
- urlencoded.js:82 urlencodedParser
[api]/[body-parser]/lib/types/urlencoded.js:82:7
When I attempt to authenticate with my API using the API key and secret that I have set, it throws the following error no matter what url path I attempt to connect to.
<pre>MissingRequiredHeadersError: Missing required HTTP headers : authorization.<br> at Object.parseRequest (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\api-key-auth\lib\parser.js:31:13)<br> at middleware (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\api-key-auth\lib\index.js:42:32)<br> at Layer.handle [as handle_request] (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\express\lib\router\layer.js:95:5)<br> at trim_prefix (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\express\lib\router\index.js:317:13)<br> at C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\express\lib\router\index.js:284:7<br> at Function.process_params (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\express\lib\router\index.js:335:12)<br> at next (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\express\lib\router\index.js:275:10)<br> at jsonParser (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\body-parser\lib\types\json.js:110:7)<br> at Layer.handle [as handle_request] (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\express\lib\router\layer.js:95:5)<br> at trim_prefix (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\express\lib\router\index.js:317:13)<br> at C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\express\lib\router\index.js:284:7<br> at Function.process_params (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\express\lib\router\index.js:335:12)<br> at next (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\express\lib\router\index.js:275:10)<br> at urlencodedParser (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\body-parser\lib\types\urlencoded.js:91:7)<br> at Layer.handle [as handle_request] (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\express\lib\router\layer.js:95:5)<br> at trim_prefix (C:\Users\ma394545\Desktop\GitHub\beaverworx-api\node_modules\express\lib\router\index.js:317:13)</pre>
I tired your example and the signature help file to create a request using the following, but I kept receiving bad signature:
what am I doing wrong?
thanks
const crypto = require('crypto');
const currentDate = new Date().toString();
const signingString = date: ${currentDate}
;
const signature = crypto
.createHmac('sha1', '123456789')
.update(signingString)
.digest('base64');
My request is:
`POST /protected HTTP/1.1
Host: localhost:3000
Accept: application/json
Authorization: Signature keyId="123456789",algorithm="hmac-sha1",signature="${signature}"
date: ${currentDate}
Content-Length: 85
Code_1=5555&Code_2=99999`
signatureParams.signingString += (request-target): ${req.method.toLowerCase()} ${req.path}
;
results:
'(request-target): get function getPath() {
return this.getUrl().pathname;
}
'
req.path() replace req.path ,can work
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.