Chapter 07 of 11
Mutual TLS, Cookies and Custom HMAC Schemes
Certificates as identity at the transport layer, cookies and CSRF, and why a home-grown signing scheme is usually a worse version of one that already exists.
The previous chapters covered the schemes an API testing tool typically configures for you. This one covers three that sit outside that set, because a complete picture is worth more than a tidy one.
Mutual TLS
Ordinary TLS authenticates the server to the client. Mutual TLS adds the other direction, so the client presents a certificate during the handshake and the server verifies it against a trusted authority.
Identity is therefore established before any HTTP is exchanged. The application receives a connection that is already authenticated, and it reads the subject from the certificate instead of parsing a header.
What it buys. The credential never travels as a value that can be replayed, because possession of the private key is proven by the handshake. Nothing in the application layer can leak it, since there is nothing in the application layer to leak. It is the strongest commonly available option between parties who can manage certificates, which is why it is standard in payments, in healthcare integrations and increasingly inside service meshes.
What it costs. A certificate lifecycle. Issuing, distributing, renewing and revoking certificates for every client is real operational work, and an expired certificate is an outage rather than a login prompt. Load balancers and proxies have to be configured to pass the client identity through. Forgetting that step is why an application suddenly cannot see who called.
Mutual TLS is usually combined with something at the application layer, not a replacement for it. The certificate says which machine connected, and a token still says which user or which permission set is in play.
Session cookies
For a browser talking to your own API on your own domain, a cookie is often the better answer than a token, and the reason is where the credential can be read from.
A token in localStorage is readable by any script that runs on the page, which means any successful cross-site scripting becomes a stolen credential. A cookie marked HttpOnly is not readable by script at all.
The attributes are the whole design.
| Attribute | Effect |
|---|---|
HttpOnly | JavaScript cannot read the cookie, which removes the main exfiltration path |
Secure | The cookie is only sent over HTTPS |
SameSite=Lax | Sent on top-level navigations but not on cross-site subrequests, and a sensible default |
SameSite=Strict | Never sent cross-site, which breaks incoming links into authenticated pages |
SameSite=None | Sent cross-site, and it requires Secure, so use it only when you genuinely need a cross-origin session |
Path and Domain | Narrow the scope, and a cookie set on a parent domain is sent to every subdomain |
Cookies bring their own problem, namely cross-site request forgery. Because the browser attaches them automatically, another site can cause the visitor's browser to send an authenticated request to yours. Three defences exist and they compose.
SameSite removes most of the attack surface on its own, and it is not sufficient alone because browser behaviour and edge cases vary.
A token the attacking page cannot read, either as a value the page must echo back in a header, or as a pair where a cookie and a header must match.
Checking the Origin header on state-changing requests, because it is cheap and catches what the other two miss.
The other consequence of cookies is that they are a poor fit for anything that is not a browser. A mobile application or a service-to-service call has no cookie jar semantics to rely on, and a token is simpler there.
Custom HMAC schemes
At some point somebody proposes a signing scheme of their own. It usually looks reasonable, and it usually has at least one of the following holes.
Ambiguous canonicalisation. If the string being signed can be produced two ways from one request, an attacker can construct a second request with the same signature. Sorting rules, encoding rules and header selection all have to be defined precisely.
Nothing to stop replay. A signature without a timestamp and a nonce is a bearer credential with extra steps, because a captured request can be sent again indefinitely.
Incomplete coverage. A signature over the path but not the body lets a proxy change the body. A signature over the body but not the method lets a GET become a DELETE.
No key rotation. A scheme with no key identifier cannot rotate keys without a coordinated cutover, so the keys never rotate.
Timing-sensitive comparison. Comparing signatures with an ordinary string comparison leaks information through timing, and a constant-time comparison is required.
Each of these is solved in the published schemes, and each solution was reviewed by people who attack protocols for a living. Where you need signed requests, take one of them instead of inventing a sixth.
The one legitimate case for a bespoke scheme is a narrow internal one where nothing published fits. Even then the shape should copy an existing specification closely enough that a reviewer recognises it.
Where these three leave the tooling
None of the three is a scheme a testing tool configures with a form field, and the reasons differ.
Mutual TLS is a transport concern, so it is configured at the client or the proxy, not in a request. Cookies are managed by a browser, and a test that needs one usually authenticates first and carries the value forward. A custom HMAC scheme is by definition not standard, so it needs code.
In Routebase
Routebase does not set up mutual TLS, session-cookie authentication or a bespoke HMAC scheme, and the catalogue covers the ten standard schemes instead.

What is available for these cases still matters.
For a cookie-based API, a test case authenticates through the login endpoint, extracts the cookie value from the response header, and passes it into later cases as a variable. That is the ordinary extraction and chaining described in workflow tests. A scenario that starts with a login step and continues with authenticated calls covers the flow end to end.
For a custom signature, the scripting sandbox on a test case runs a pre-request script that computes the value and sets the header before the request goes out. That is the escape hatch for anything the declarative catalogue does not name.
For mutual TLS, there is no configuration surface, and a service that requires it is reachable from Routebase only through something that terminates the client certificate on your side.
If one of these becomes a requirement for your team, it is worth telling us instead of working around it, because the catalogue grows from what customers actually run. See Project Auth for the schemes that are configured today.
Frequently asked questions
What is mutual TLS authentication?
Mutual TLS extends the normal TLS handshake so the client presents a certificate as well as the server. Identity is then established at the transport layer, before a single byte of HTTP is exchanged, and the application receives an already-authenticated connection. It gives strong assurance between parties who can manage certificates, and its cost is exactly that certificate lifecycle.
Should an API use cookies or tokens for authentication?
For a browser talking to your own API on your own domain, a cookie with HttpOnly, Secure and SameSite is usually the safer choice, because it is unreachable from injected script. For anything that is not a browser, a token is simpler, since there is no automatic sending and therefore no cross-site request forgery to defend against. The decision follows the client rather than fashion.
What is CSRF and how do cookies cause it?
Cross-site request forgery is an attack where another site causes the visitor's browser to send an authenticated request to yours. It exists because browsers attach cookies automatically to requests for a domain, whatever page started them. The defences are the SameSite cookie attribute, a token the attacking page cannot read, and checking the Origin header, and a cookie-based API should use more than one of them.
Should you build a custom HMAC authentication scheme?
Almost never, because the published schemes already solved the problems you will meet and had their solutions reviewed. A custom scheme has to define canonicalisation, replay protection, key rotation and error handling correctly on the first attempt, and getting any one of them wrong is silent. Where you need signed requests, take an existing specification and implement it faithfully.
Last reviewed by The Routebase Team.