Survey tokens, expiry, and tamper rejection
Each survey is signed with a token tied to the conversation, customer, kind, and time. Tokens expire (default 30 days). Tampering is rejected.
Every Ochre survey contains a token. The token is what makes the survey work without forcing the customer to log in. Click an emoji button in an email, the token authenticates you, your rating is recorded. No password, no friction.
This page covers how the token works, what it protects against, and what its expiration window is.
What the token contains
A survey token is an HMAC-signed value of the form <base64url-payload>.<base64url-signature>. The payload encodes:
- The conversation ID the survey is for.
- The customer (end user) the survey is addressed to.
- The kind of survey (
csatornps). - A timestamp (
ts) of when the token was issued (milliseconds since epoch).
The signature is HMAC-SHA256 over the payload, using a server-side secret. If a token arrives at the response endpoint with any field tampered with, the signature fails and the response is rejected.
What tokens prevent
Tokens prevent three failure modes:
- Forgery. Someone can't make up a survey URL and submit a fake rating. The HMAC signature requires the server-side secret, which only the Ochre backend has.
- Replay across customers. A token is bound to one conversation and one customer. You can't take customer A's survey link and submit it as customer B.
- Tampering with kind / conversation. Changing the survey kind or conversation ID in the payload invalidates the signature.
What tokens don't prevent: a customer voluntarily forwarding their own survey link to a friend who then submits the rating. We accept this risk because the alternative (forcing login for every survey) destroys response rates. In practice, customers don't do this.
Server-side invite tracking
Each token also has a corresponding row in the survey_invites table. When a customer submits a response, the system:
- Verifies the HMAC signature.
- Decodes the payload and checks the timestamp is within TTL.
- Looks up the matching
survey_invitesrow to confirm we issued this token, it hasn't been responded to, and it hasn't expired. - Records the response against the invite.
This dual approach (signed token plus server-side row) is belt-and-suspenders: the signature alone proves authenticity without a DB hit, and the DB row prevents replay (each invite resolves once) and powers analytics.
Expiration
Tokens expire 30 days after issue. After expiration, the survey link still loads, but instead of accepting a rating it shows a friendly "this survey link has expired" message.
The 30-day window balances two concerns:
- Customers respond on their own schedule. Some customers respond within an hour. Others see the email a week later, decide to respond, and would be frustrated by an "expired" message after 24 hours.
- Stale tokens add risk. Letting tokens live for a year means that if one ever leaks, it's exploitable for a year. Thirty days is a reasonable cap.
What customers see when something fails
Tokens can fail for a few reasons. The customer-facing messages are friendly and don't expose internal details:
- Expired token: "This survey link has expired. Thanks for considering it."
- Already used: "Looks like this survey was already answered. Thanks!"
- Invalid signature (tampering or forgery): a generic friendly fallback.
- Conversation not found: same fallback.
In every case, no internal data is leaked.
Tokens and customer privacy
Tokens look like long random strings. They don't expose the customer's email, the conversation contents, or any other internal data. If a customer accidentally shares a survey URL publicly (in a screenshot, for example), the URL itself doesn't leak anything beyond what the holder can do with it (submit a single rating against the conversation).
Standard hygiene applies: don't paste survey URLs into shared chats, don't screenshot them with the URL bar visible.
The HMAC secret
The HMAC secret is a server-side value Ochre keeps in environment configuration. The dedicated environment variable is OCHRE_SURVEY_TOKEN_SECRET, separated from any other workspace secret so it can be rotated independently without affecting service-role access elsewhere.
For continuity, the verifier accepts tokens signed with either the current dedicated secret or a legacy fallback during a rotation window — so existing 30-day tokens keep validating while new tokens move to the new secret. Customers see no disruption from a rotation.
Related
Was this article helpful?