HMAC Authentication spike

advertisement

HMAC Authentication

Flow of using API Key – HMAC Authentication:

Note: First of all the server should provide the client with a public (APP Id) and shared private secret

(API Key), the client responsibility is to store the API Key securely and never share it with other parties.

Flow on the client side:

Client should build a string by combining all the data that will be sent, this string contains the following parameters (APP Id, HTTP method, request URI, request time stamp, nonce, and Base 64 string representation of the request pay load).

Note: Request time stamp is calculated using UNIX time (number of seconds since Jan. 1st 1970) to overcome any issues related to a different timezone between client and server. Nonce: is an arbitrary number/string used only once. More about this later.

Client will hash this large string built in the first step using a hash algorithm such as (SHA256) and the API Key assigned to it, the result for this hash is a unique signature for this request.

The signature will be sent in the Authorization header using a custom scheme such as”amx”. The data in the Authorization header will contain the APP Id, request time stamp, and nonce separated by colon ‘:’. The format for the Authorization header will be like: [Authorization: amx

APPId:Signature:Nonce:Timestamp].

Client send the request as usual along with the data generated in step 3 in the Authorization header.

Flow on the server side:

Server receives all the data included in the request along with the Authorization header.

Server extracts the values (APP Id, Signature, Nonce and Request Time stamp) from the

Authorization header.

Servers looks for the APP Id in a certain secure repository (DB, Configuration file, etc…) to get the

API Key for this client.

Assuming the server was able to look up this APP Id from the repository, it will be responsible to validate if this request is a replay request and reject it, so it will prevent the API from any replay attacks. This is why we’ve used a request time stamp along with nonce generated at the client, and both values have been included into HMAC signature generation. The server will depend on the nonce to check if it was used before within certain acceptable bounds, i.e. 5 minutes. More about this later.

Server will rebuild a string containing the same data received in the request by adhering to the same parameters orders and encoding followed in the client application, usually this agreement is done up front between the client application and the back-end service and shared using proper documentation.

Server will hash the string generated in previous step using the same hashing algorithm used by the client (SHA256) and the same API Key obtained from the secure repository for this client.

The result of this hash function (signature) generated at the server will be compared to the signature sent by the client, if they are equal then server will consider this call authentic and process the request, otherwise the server will reject the request and returns HTTP status code 401 unauthorized.

Approaches

Approach 1:

Introduce a new message handler i.e. in ServicesRoutingManager.cs

GlobalConfiguration.Configuration.MessageHandlers.Add(new BasicAuthMessageHandler());

GlobalConfiguration.Configuration.MessageHandlers.Add(new

DigestAuthMessageHandler());

GlobalConfiguration.Configuration.MessageHandlers.Add(new

HMACAuthMessageHandler());

GlobalConfiguration.Configuration.MessageHandlers.Add(new

WebFormsAuthMessageHandler());

Pros

Similar to existing authentication message handlers

Allows HMAC to indentify user, who is later signed in by WebFormsAuthMessageHandler - as such they can then use any existing attribute (though those that use portalid/tabid/moduleid make no sense)

Cons

Proving a little tricky to get working

Add’s an additional check for each service framework request (though this is shortcircuited quickly via a header check)

Assumes all service framework methods work - for a better security boundary we would likely still need an attribute to indicate support e.g. [SupportsHMAC]

Approach 2:

Implement as an authentication filter attribute - an example of similar code can be found at https://github.com/tjoudeh/WebApiHMACAuthentication/blob/master/HMACAuthentication.WebA

pi/Filters/HMACAuthenticationAttribute.cs

(http://www.codeproject.com/Articles/766171/ApiFrame-A-simple-library-for-Web-API-security-exc is another good alternative)

Pro’s

Lots of working examples

Only adds an overhead if method is decorated with attribute

Con’s

WebAPI defaults to anonymous access to all web methods. Services Framework defaults to requiring host permissions to access a method. This is implemented by dynamically inserting a RequiresHost auth filter in the list of action filters run on a method. Services Framework implements it's own IFilterProvider in DnnActionFilterProvider to manage the dynamic insertion of the RequiresHost auth filter. This may complicate integration of a new authentication filter attribute.

Testing:

https://github.com/dnclabs/hmac-dot-net-tester

Additional Work required (independent of approach)

1.

Introduction of an AppID - a decision would need made if this is host or portal specific.

Changing this would also invalidate all connected applications (perhaps a useful security mechanism)

2.

Addition of “shared secret” field and “enable HMAC” fields at user level - UI would be needed to enable HMAC and to generate a shared secret.

3.

Installable extension that would allow QA to validate - this would need to cover any attribute usage, a method by which to prove the caller identity (principal), as well as GET and

POST methods.

Download