One of the primary design goals of the Hawk scheme is to “simplify and improve HTTP authentication for services that are unwilling or unable to deploy TLS for all resources”. It is highly recommended to use TLS (HTTPS) even with Hawk but the design goal of Hawk is to ensure the working of the scheme in the absence of HTTPS as well. I covered the basics of Hawk and how the request payload can be protected by Hawk. In the absence of TLS, a man-in-the-middle (MITM) can tamper with the web API response even if the request is protected. One of the key aspects related to preventing the responses getting tampered is the response payload verification and it works like this.
 The client creates the HTTP authorization header in the Hawk scheme with all the fields.
Authorization: Hawk id="dh37fgj492je", ts="1353832234", nonce="j4h3g2", hash="Yi9LfIIFRtBEP=", ext="some-app-ext-data", mac="aSe1DEReKjVw="
If you are using Thinktecture.IdentityModel.45 in the client side, HawkValidationHandler creates this header by calling the CreateClientAuthorizationAsync method of HawkClient.
 The server authenticates the request by validating the data in the Authorization header. In case of ASP.NET Web API using Thinktecture.IdentityModel.45, HawkAuthenticationHandler performs this validation by calling the AuthenticateAsync method of HawkServer.
 When all is well, [Authorize] filter (if any) running in the pipeline has no objection, the action method of the controller executes and returns the response to be serialized.
 Exactly similar to step #1, the server creates the Server-Authorization header for the same id, ts, and nonce in the request. Application specific data ext can be different in the response compared to the one from the request. Payload hash hash is the hash of the response payload. Using all these, server calculates the mac and creates a header like so.
Server-Authorization: Hawk mac="XIJRsMl/4oL+nn+vKoeVZPdCHXB4yJkNnBbTbHFZUYE=", hash="f9cDF/TDm7TkYRLnGwRMfeDzT6LixQVLvrIKhh0vgmM=", ext="response-specific"
HawkAuthenticationHandler performs this step by calling the CreateServerAuthorizationAsync method of HawkServer.
 The client receives the response and validates the same. This is very similar to step #2. HawkValidationHandler performs this validation by calling the AuthenticateAsync method of HawkClient. The EnableResponseValidation property of ClientOptions determines if the client validates the response or not (true/false).
The server-side setting for generating the Server-Authorization response header is the EnableServerAuthorization property of Options class. If this property is set to true, the Server-Authorization response header is sent for status codes other than 401. Why not create the Server-Authorization for 401? The problem is the server will not have the right symmetric key to create the header in that case. Authentication has failed and that is the reason for 401 in the first place and this means the server will not be able to pick the right key. So, what if a MITM tampers the response? There are two cases possible. Server sends 401 and MITM changes it to 200 and puts in an evil response. If the client is enabled to check the response, this will fail because MITM will not have the key to compute the MAC correctly. The second case is that the server sends 200 but MITM changes it to a 401. In this case, MITM cannot send some bad data. Integrity is not compromised and it becomes a case of denial of service. It is still bad but not as bad as the client getting tampered data. It is possible to protect even the status code through the ext field, which will be the subject of my next post.
Given this symmetrical nature of the steps in the HTTP transaction: the client creating a header, the server validating it and then the server creating a header and the client validating it, I used two message handlers – one in the client side and one in the server side, namely HawkValidationHandler and HawkAuthenticationHandler and they respectively use the core class of HawkClient and HawkServer to perform their duties.
If you do not use HttpClient and hence cannot use HawkValidationHandler, you can feel free to use HawkClient directly. Similarly, if you want to use Hawk with a framework other than ASP.NET Web API, you can call HawkServer directly, along the lines of how HawkAuthenticationHandler does it.