I'm working on authentication for my JSON-RPC API
and my current working strategy is using signed requests sent via POST
over SSL
.
I'm wondering if anyone can see any vulnerabilities that I haven't taken into consideration with the following signature method.
All communication between the client and the server is done via POST
requests sent over SSL
. Insecure http
requests are denied outright by the API server.
Dependencies
var uuid = require('node-uuid');
var crypto = require('crypto');
var moment = require('moment');
var MyAPI = require('request-json').newClient('https://api.myappdomain.com');
Vars
var apiVersion = '1.0';
var publicKey = 'MY_PUBLIC_KEY_UUID';
var secretKey = 'MY_SECRET_KEY_UUID';
Request Object
var request = {
requestID : uuid.v4(),
apiVersion : apiVersion,
nonce : uuid.v4(),
timestamp : moment.utc( new Date() ),
params : params
}
Signature
var signature = crypto.createHmac('sha512',secretKey).update(JSON.stringify(request)).digest('hex');
Payload Packaging (Sent as cleartext via POST over TLS)
var payload = {
request: request,
publicKey : publicKey,
signature : signature
}
POST Request
MyAPI.post('/', payload, function(error, response, body){
console.log(result);
});
Resultant Payload
{
"request" : {
"requestID" : "687de6b4-bb02-4d2c-8d3a-adeacd2d183e",
"apiVersion" : "1.0",
"nonce" : "eb7e4171-9e23-408a-aa2b-cd437a78af22",
"timestamp" : "2014-05-23T01:36:52.225Z",
"params" : {
"class" : "User"
"method" : "getProfile",
"data" : {
"id" : "SOME_USER_ID"
}
}
},
"publicKey" : "PUBLIC_KEY",
"signature" : "7e0a06b560220c24f8eefda1fda792e428abb0057998d5925cf77563a20ec7b645dacdf96da3fc57e1918950719a7da70a042b44eb27eabc889adef95ea994d1",
}
Server-Side
And then on the server-side the following occurs to authenticate the request:
- PUBLIC_KEY is used to lookup the SECRET_KEY in the DB.
- SECRET_KEY is used to create an HMAC of the
request
object from the payload. - The hash sent in the payload is compared to the hash created on the server. If they match, the PUBLIC_KEY is authenticated.
- The
timestamp
is evaluated and the authentication is rejected if the request is too old, otherwise, the timestamp is authenticated.
So far as I understand, this is a secure method for signing and authentication requests sent over SSL
. Is this correct?
Thanks in advance for any help.