Short answer: For marketplace documents sent to outside parties, expiring access limits future retrieval; a watermark identifies the intended recipient after a copy leaves your control. Neither prevents a recipient from leaking bytes already downloaded. Keep the document template under the team's control when recipient-specific marks, regeneration, and auditability matter; let a shared rendering component apply a versioned template at delivery time. The choice is about who can change the mark without rebuilding every client.
| Sharing path | Expiring access | Recipient watermark | Template owner |
|---|---|---|---|
| Authenticated viewer | Refuse new requests after expiry | Label each rendered copy | Document team owns the template |
| Downloadable attachment | Expiry stops later downloads, not existing files | Label the exported bytes | Document team owns the template |
| Forwarded, unmarked original | No control over forwarded bytes | No attribution | Fix the export path first |
The recommendation is to use both controls for external sharing, but treat the template as an owned security artifact, not an arbitrary client-supplied string. A marketplace may send the same listing dossier to three prospective buyers. If one export carries the wrong buyer identifier, the watermark can mislead an investigation. That is worse than a missing flourish on a PDF. The trade-off is real: each recipient-specific export consumes rendering work and creates another artifact to retain, audit, and eventually delete under the team's retention policy. For high-volume, low-sensitivity public listings, that complexity may be unjustified; restrict the protected workflow to the documents that actually cross a confidentiality boundary.
Can a watermark or expiring access control prevent a document leak after download?
Expiry is a gate on a request. It works only where the recipient must return to the controlled endpoint. Enforce it on every retrieval, including preview and download, and check authorization against the document and intended recipient rather than assuming possession of a link proves permission. OWASP's authorization guidance calls for validating permission on every request and denying access by default.
Once a recipient has the file, the gate is behind them. They can retain or forward that copy. A visible watermark can tell a later viewer which recipient the copy was prepared for, but it does not block screenshots, photography, editing, or deliberate removal. Keep claims narrow: a watermark helps attribution when the marked content survives; expiration limits subsequent access through your service. Neither establishes who actually disclosed a file.
The bytes remain.
This changes the operational question. Test an expired link at the viewer, preview, and download boundaries, then inspect the actual exported PDF. A UI banner saying "expired" is not an access check. Likewise, a watermark displayed only by the viewer disappears when an unmarked original is downloaded.
Who gets to change the watermark template?
Template ownership is the harder decision. The document team should define the placement, text fields, and revision of the mark; the sharing service should supply only validated recipient and document data. If every SDK assembles its own watermark, a field rename or layout change becomes a multi-client rollout. If callers can supply arbitrary watermark text, they can produce inconsistent or misleading labels. The central template keeps the rendered result reviewable while the access service stays responsible for permissions.
Store a template version with the generated artifact and the share record. The exact placement deserves a visual test on representative pages: cover pages, dense tables, and scans behave differently. The PDF format is standardized by ISO 32000-2, but the standard does not decide whether your mark is legible or whether sensitive content remains visible under it. For a marketplace dossier that mixes a full-page scan with a dense pricing table, test both: a mark that reads clearly on white paper may vanish on the scan, while a heavy overlay can obscure numbers on the table. Render and inspect each output class before release. Do not infer visual quality from a successful file write.
Here is the boundary I would expose to an SDK. The caller asks for a share; the service determines which template version to render and authorizes each retrieval. The types make the distinction between expiry and document bytes explicit.
type ShareRequest = {
documentId: string;
recipientId: string;
expiresAt: string;
};
type ShareRecord = ShareRequest & {
shareId: string;
templateVersion: string;
artifactId: string;
};
async function issueShare(input: ShareRequest): Promise<ShareRecord> {
const recipient = await loadAuthorizedRecipient(input.documentId, input.recipientId);
const template = await loadActiveWatermarkTemplate(input.documentId);
const artifactId = await renderMarkedArtifact({
documentId: input.documentId,
label: recipient.displayLabel,
template,
});
return persistShare({ ...input, templateVersion: template.version, artifactId });
}
async function retrieveShare(shareId: string, requesterId: string): Promise<Uint8Array> {
const share = await loadShare(shareId);
if (!share || share.recipientId !== requesterId || Date.now() >= Date.parse(share.expiresAt)) {
throw new Error("Access denied");
}
return loadArtifact(share.artifactId);
}
The example assumes authenticated recipient IDs, a trusted clock, and a separate authorization check before issuance. It is an interface sketch, not a claim that a URL or client clock is an access-control system. Never log the full document or recipient label just to debug a rendering failure; log the share ID, template version, decision, and failure stage. Retry rendering with an idempotent share request so a timeout does not create two differently marked artifacts for one recipient. This design is not suitable for a workflow that requires previously downloaded files to become unreadable on demand: neither a PDF watermark nor endpoint expiry can revoke those bytes. Use a controlled viewer with no export path for that requirement, and still account for screen capture.
No magic revoke switch.
When is a lighter template model enough?
The runner-up is a fixed, centrally configured mark with no per-document template lifecycle. It fits documents with one consistent layout and a small number of stable recipient fields. There is less configuration to review and less glue in the client. Good. Keep it until variation becomes a real requirement, not a hypothetical one.
Move to versioned, document-owned templates when different document classes need distinct placement or when an audit must reconstruct what a recipient received. Benchmark the work that matters: time from share request to first usable file, render latency across representative page counts, and the fraction of exports whose mark passes visual inspection. Do not invent a throughput target before measuring the PDFs you actually send. Preserve the prior template while in-flight shares finish, and record the version on every artifact so a later edit cannot silently rewrite history.
The decision rule is plain: if recipients can download, use expiry for future requests and embed a recipient mark in the exported file; assign template ownership to the team accountable for document content. If distribution never leaves a controlled viewer, start with authorization and expiry, then add a mark only when its attribution value justifies the rendering and review work.
References
- ISO 32000-2, Portable Document Format: https://www.iso.org/standard/75839.html
- OWASP Authorization Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html
Top comments (0)