Your app serves each receipt through a signed time-limited link, and a user pastes one into a group chat — who can read it?
answer
- possession is the authorisation
- the store checks proof, not identity
- bounded in time, not in audience
- the signer's authority is what travels
- the lifetime is the blast radius
basics
~20 sAnyone holding the link, until it expires. A signed time-limited link is a bearer credential in a URL: the store checks the signature and the clock, not the identity of whoever presents it. It bounds exposure in time, not in audience.
solid answer
~40 sThe link carries its own proof. The store verifies that the signature matches the object, the method and the expiry encoded in the URL, and that the expiry is still in the future — it never asks who is holding it. So everyone in that group chat can fetch the receipt, and so can anyone they forward it to, until the moment it expires. What the signature authenticates is the authority of the **signer**: it is minted using credentials that could already read the object, which is why a link can never grant more than its signer had. The design still beats making the object public, because the exposure ends by itself and every issuance is a decision your service made and can record.
code
http · 12 linesGET /receipts/2026-08/r-4417.pdf?expires=1757980800&signature=b41f9c2e HTTP/1.1
Host: objects.store.example
HTTP/1.1 200 OK
Content-Type: application/pdf
--- the same request after the expiry timestamp has passed ---
GET /receipts/2026-08/r-4417.pdf?expires=1757980800&signature=b41f9c2e HTTP/1.1
Host: objects.store.example
HTTP/1.1 403 Forbiddengo deeper
Know that a signed time-limited link works for whoever holds it until it expires. There is no login step, so sharing the URL shares the access.
Explain what the store verifies — signature, object, method, expiry — and that the authority being delegated is the signer's, so a link can never exceed it.
Show the operational consequences: mint per request with the shortest workable lifetime, prefer a short-lived signing credential, and know that revocation is blunt or impossible.
The trade-off is where the per-user authorisation decision lives. Serving directly from the store is cheap and fast, but it moves that decision to link-minting time and gives up the ability to change your mind mid-flight.
The mobile backend never proxies receipt bytes through itself; it hands the app a signed time-limited link and lets the store serve the object directly. A user pastes one of those links into a group chat. Working out who can now read the receipt is the whole point of understanding what the signature is. ## What the signature actually is A signed link is a URL that carries its own proof of authorisation in its query parameters: which object, which method, when it expires, and a signature computed over those values with a credential that was already allowed to perform that action. When the request arrives the store: - recomputes the signature over the parameters presented and checks it matches; - checks the expiry is still in the future; - checks that the signing credential's own permission covers the action. Notice what is missing. The store never establishes **who is holding the link**. There is no login, no credential in a header, no session. That makes the link a **bearer credential**: possession is the authorisation. ## What it bounds and what it does not | Dimension | Bounded by a signed link? | Consequence | |---|---|---| | Time | yes — the expiry is signed in | exposure ends by itself | | Object and method | yes, if you sign narrowly | a read link cannot be turned into a write | | Audience | **no** | anyone in possession can use it | | Onward sharing | no | forwarding costs nothing and leaves no trace | So the honest answer to the group-chat question is: every member of that chat, plus anyone they forward it to, plus anything that automatically fetches URLs in that chat — link previews, archiving bots, an indexing crawler if the message lands somewhere reachable — for exactly as long as the link remains valid. ## Why it still beats making the object public A permanent public grant on the store and a signed link both let an unauthenticated fetch succeed, and they differ in three ways that matter: 1. **The exposure expires.** A leaked link is a time-boxed incident; a public grant is open until someone notices and edits it. 2. **Each issuance is an authorisation decision.** Your service decides, per request, that this user may see this receipt — enforcing per-user rules the store knows nothing about — and can record it. 3. **The scope is per object.** A link exposes one object, not a store someone can enumerate. That is why the signed link is the right default for user-owned documents and the public grant is not. ## Choosing a lifetime The lifetime is the entire blast radius, so make it as short as the client honestly needs: - **Mint per request**, not per session, and never cache a link beyond its purpose. - Size it to the **use**: seconds-to-minutes for an image the app is about to render, longer only for something a human must download over a slow connection. - Remember a long expiry converts a transient leak into a durable one, and that **the link cannot be recalled** — once signed, it is valid until it expires, whatever you change afterwards about the user's account. - Where the platform supports it, prefer signing with a **short-lived credential**, since a link cannot outlive the authority that signed it when that authority is itself short-lived. ## Where links leak in practice URLs are the least private part of a request. They land in server and proxy access logs, in browser history, in referrer headers when the page links onward, in chat previews and screenshots, and in bug reports pasted verbatim. Treat a signed link as something that **will** be seen by someone you did not intend, and choose a lifetime you could live with that being true of. Finally, a signed link answers "may this fetch proceed", not "who is this person". If a receipt should be visible to one user and no other, that decision belongs in your service before the link is minted — the link cannot enforce it afterwards.
- A user's account is disabled one minute after their app fetched a link. Can they still read the object?Yes, until the link expires. The store verifies the signature and the clock, not the current state of the end user's account, and your service is not in the request path to object. That is the argument for short lifetimes and for signing with short-lived credentials, whose own expiry caps the link's usefulness.
- Can a signed link grant more access than the identity that signed it had?No. The signature is computed with a credential, and the store still checks that credential's permission for the action at request time. A link signed by an identity that may only read one key prefix cannot be edited into a valid link for another. It delegates existing authority; it does not create any.
- How do you actually revoke a signed link that has leaked?You mostly cannot revoke the link itself. The practical levers are invalidating the signing credential where the platform ties links to it, moving or renaming the object so the signed path no longer resolves, or deleting it. All are blunt and affect every outstanding link, which is the real reason to keep lifetimes short.
A hotel key card that stops working at checkout time. It does not know whose hand it is in — anyone who picks it up can open the door until the card goes dead on its own.
saying these in an interview costs you the question
- Says the link identifies the user presenting it
- Thinks a leaked link stops working once sharing is noticed
- Sets long expiries because clients occasionally retry
- Believes a signed link can grant access the signer lacked
- Treats a URL as private because it is long and random