For a HTTP(S) API, which is better (/ which is better under which circumstances)?

  • Hawk authentication (a secret key is used to create a signature which is transmitted with the request: similar to AWS Signature v4)
  • API key authentication (a secret key itself transmitted with the request)

A downside of Hawk is that since the secret key isn't transmitted, but just a signature, then the server has to store the secret part of the key somewhere in plain text (/ able to convert it to plain text) in order to sign the incoming requests itself to compare to the incoming signature.

A downside of the API key is that the secret key itself is transmitted.

(Acceptable answers could include "neither: instead do X in circumstance Y because Z")


This is how I would rank preference for auth mechanisms from a security standpoint.

  1. Asymmetric - Mutual TLS
  2. Asymmetric - Signature based JWS like.
  3. Symmetric - HMAC or a similar symmetric signature based
  4. Pre shared credential based

I will try to articulate the rationale behind my reasoning below. With authentication ideally we should be able to tackle the following security problems or requirements.

  • Authentication
  • Non-Repudiation
  • Key Exchange Security
  • Message integrity
  • Replay Protection

    1. Asymmetric - Mutual TLS

Usually when you are accessing an HTTPS website, the browser validates the server certificate. This is a part of the TLS handshake. In mutual TLS, the client certificate is also validated by the server during the handshake process. The protocol itself handles majority of the security properties and you only have to worry about the keys are protected and are of sufficient length.

  1. Asymmetric - Signature based

If you already are using HTTPS for confidentiality and integrity, you can use JWS or similar signature schemes for signing message payload with an asymmetric key. JWS standard itself offers both symmetric and asymmetric signature options [HS - HMAC based, RS - RSA PKCS1.5 and PS - RSA PSS]. HS options should be ignored as they don't provide non repudiation capability. To acheive replay protection, a nonce or a timestamp must be included to the payload. Note that this would be defense in depth if the channel is HTTPS. Also be aware of pitfalls with specific implementations of JWS. [eg: alg : None]

  1. Symmetric - HMAC based

The mere existence of a shared key makes non repudiation impossible. The client can claim that the server is also in possession of the key and hence claim that the message was not sent by them. There is no cryptographic way for the server to negate such a claim.

  1. Preshared key

This is the easiest form of authentication but the problem is that it only provides the property of authentication and opens up various attack channels during the key exchange.

To summarise:

  • 1 provides all the security properties as a protocol.
  • 2 provides all the properties if you design it right.
  • 3 provides authentication and message integrity but provides no non repudiation. It also involves a key exchange which adds another point of failure. It can be designed to provide replay protection.
  • 4 provides authentication. Non repudiation, message integrity or replay protection is not provided. Since the key sent in every message is the same, it increases the likelihood of a key compromise.
  • Mutual TLS doesn't provide with non-repudiation because of PFS - you need to log not only the TLS session, but ephemeral Diffie-Hellman secrets as well. Which is technically both complicated and stupid. So instead typically you sign request body in addition to TLS, and store the signed body in audit logs to show in a court. Unfortunately there are no good standards. – nponeccop Feb 27 at 2:31
  • @nponeccop Makes sense and I think you are right about non-repudiation being difficult with mutual TLS unless do it in a hacky way. I will find a way to edit the answer appropriately. Thank you. – hax Apr 14 at 15:56

AFAIK, the standard way is to use asymetric keys for signing:

  • the private key is only known by the sender
  • the request is hashed with a standard algorithm, and that hash is encrypted with the private key to form a signature which is transmitted with the request
  • the server uses the public key to decrypt the signature and control that it corresponds to the message.

That way:

  • no secret has to be shared
  • no secret is transmitted
  • assuming a cryptographic secure hash, it is admitted that it is not possible to build a request corresponding to a given hash

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.