How Signed Handoff Tokens Work

Passing login state safely with a single-use token that is valid only at the moment of crossing sites

Signed tokenHMACExpirySecurityAuthentication
9 min read

Introduction

Once you decide to share a single login across sites that run on separate domains, the next question is what exactly gets handed over, and how.

The goal is to tell the destination site "this person is already logged in" without making them type a password again. The short string used for that handover is the handoff token — the piece at the centre of cross-site single sign-on (SSO).

The catch is that whatever you hand over has to be designed on the assumption that it can be stolen or rewritten along the way. Get this part wrong and a convenience feature turns into a way for someone to impersonate another user. This article covers what goes into the token, how forgery is prevented, and why it only stays usable for a few dozen seconds. It's about the reasoning behind the choices, not how the code is written.

What Goes Into the Token

Who, Where, and Until When

A handoff token is a small bundle of information. At minimum it carries these five things.

What the table shows is that a token contains just two kinds of thing: the minimum information needed to carry a login over, and proof that this information is genuine.

The first three fields tell the receiving side whose login to accept, for which site, and for how long. The last two let it check mechanically whether those fields can be trusted. Because the roles are cleanly split, deciding whether to add a new field later is a matter of asking which of the two groups it belongs to.

No Passwords, No Personal Data

The important rule is that no secret — a password, payment details — ever goes into the token. It stays strictly a temporary permit that says "you may carry this user's login over."

The reason is simple: it changes how bad a leak would be. If a password were inside, anyone holding the token could impersonate the user completely. A handover permit, by contrast, allows nothing beyond "create a login state, on that one site, once, within the expiry window." You're capping the worst case at design time.

Carrying Less Is Itself a Safeguard

The token travels to the other site attached to a URL. That means it can end up recorded as text in browser history and in server access logs.

So the only information it carries is information that's acceptable to leave behind. Even the user identifier isn't the internal member number — it's a reference value created purely for handovers. Email addresses and names stay out for the same reason. Keeping the contents minimal is a genuine security measure in its own right.

Preventing Forgery with a Signature

Signing with a Shared Key

The signature is what guarantees the token wasn't rewritten in transit. We used an HMAC signature: a method that uses a shared secret key to compute a short verification string from the contents.

Signing and verifying run the same calculation twice
The sender computes a signature

Site A computes a signature from the shared secret key and the token contents, then appends it

The receiver runs the same calculation

Site B recomputes the signature from the contents it received, using the same key

The two are compared

If the signature it computed matches the one attached, nothing was tampered with

What the diagram shows is that the receiving side can judge authenticity simply by repeating the same calculation.

A third party without the key can't produce a valid signature, however they rewrite the contents. So a trick like swapping the user identifier for someone else's doesn't work. Put the other way round: as long as the key is protected, it doesn't matter what path the token travelled.

A Signature Is Not Encryption

Confusing the two leads to a bad design. A signature doesn't hide anything, so the earlier rule still applies in full: only put in information you'd be comfortable having read. A signature isn't a tool for concealing contents — it's a tool for judging whether they're genuine.

Why a Shared Key Instead of Public-Key Signing

There's also public-key signing, where the issuing side and the verifying side hold different keys. That's the better fit when the other party is an outside company and you'd rather not hand them a key.

Here, every site sat under the same operator, so the same secret key could be distributed safely. Given that, the simpler mechanism means fewer operational mistakes: one type of key to manage means fewer chances to misconfigure or mix things up. We only agreed on one boundary — if a partner's site ever joins, the signing method gets revisited.

Blocking Reuse with Expiry and Single Use

A Lifespan of Only the Seconds the Move Takes

Signing prevents forgery, but a legitimate token can still be stolen. That's where a short expiry earns its place.

A handoff token exists only for the few — at most a dozen or so — seconds it takes to move between sites, so its lifespan is set extremely short. Even if it were picked out of a log or a history file, it would be long expired by the time anyone tried to use it. A token that stays valid for a long time becomes a target just by existing. The shortness isn't an inconvenience; it's the point.

A Used Token Is Invalidated Immediately

With and without single use
BEFORE
Not single-use

A stolen token can be used repeatedly while it's still valid, recreating a login state again and again

AFTER
Single-use

A token that passes verification is invalidated on the spot. A second attempt with the same token always fails

What the comparison shows is one single difference: whether the same token works twice.

The receiving side records the one-time ID of every token that passes verification, and rejects the ID if it turns up again. That shuts down replay attacks, where a stolen token gets reused. Because the second attempt fails even inside the expiry window, this is more reliable than leaning on the expiry alone.

Three Measures, Three Different Attacks

Signature, expiry, and single use don't overlap. The signature stops the contents being rewritten, the expiry stops delayed misuse, and single use stops the same token being replayed.

That's why none of them can be dropped. With only a signature, a stolen genuine token still works; with only an expiry, the contents can be swapped. The layering exists so that when one measure fails, the others still stand. Gaps in an authentication spec turn straight into incidents, so for each measure we wrote out "what becomes possible if this is missing?" before settling the design.

Decisions About Issuing and Storage

Limiting Who Can Request a Token

The endpoint that creates tokens must not be open to anyone who knocks. The first condition we set was that it only accepts requests from users already logged in on that site.

If this is loose, someone who isn't logged in could ask for "the permit for this user" and walk away with one. A token exists to carry over the result of an authentication that already happened, so there is no legitimate situation where one is issued to an unauthenticated requester.

Naming the Destination Site to Prevent Reuse

The token records which site it was issued for, and the receiving side checks whether it is the intended recipient.

Without that, a token issued for Site B could simply be carried to Site C. In a setup where every site shares the same key, the signature alone can't distinguish destinations. Recording the destination and comparing it takes one extra step and stops the token being reused across sites — an unglamorous check, but an unavoidable one once you choose a shared key.

Where the Key Lives, and Rotating It

The signing key is never written into the code. It's supplied as an environment variable (a setting passed in from outside on each server). Written into code, it would mean that anyone who saw the repository could forge signatures for every site.

We also agreed a procedure for rotating it. Since all sites reference the same value, a rotation has to happen across all of them together. It isn't something you do often, but the steps are written down so a change of staff doesn't leave anyone guessing.

Summary

A handoff token is a single-use permit valid only for the instant of crossing between sites. To recap the design:

  1. Minimal contents: no secrets, only what the handover needs
  2. A signature prevents forgery: computed with a shared key, then recomputed by the receiver
  3. A lifespan of seconds: short enough that a stolen token expires before it can be used
  4. One use only: used IDs are recorded, and a second attempt is always rejected
  5. Issuing and destination are constrained: only logged-in requests get a token, and the destination is checked

How the receiving side actually verifies the token and builds a login state is covered in "SSO Callback and Session Establishment Flow". For where SSO fits overall, see "Single Sign-On Across Multiple EC Sites", and for managing the key and the permitted-site list, see "SSO Configuration That Scales with New Sites".