Skip to content

Cache lookups of compatible key IDs safely #1095

Description

@dahlia

Background

Since #840, Fedify does not read or write the KeyCache for key IDs that are FEP-ef61 compatible identifiers, i.e., HTTP(S) URLs under /.well-known/apgateway/did:. Whether such a key is valid depends on what it is used for: a gateway key of a portable actor authenticates HTTP requests, but never Object Integrity Proofs or Linked Data Signatures. A shared cache entry would let one purpose reuse what another resolved or rejected.

The cost is that the cache also stopped protecting these key IDs from repeated lookups. Before, a request signed with a bogus key cost one fetch, and later requests with the same key ID hit the cached null and the cached fetch error. Now every such request makes Fedify fetch the document at the key ID, and, if it is a portable actor, expand it and verify its Object Integrity Proof. A sender can therefore make any Fedify inbox, or any endpoint that calls getSignedKey(), fetch any URL of this form once per request.

#840 already avoids the second fetch that doesActorOwnKey() would add for requests the inbox rejects anyway, but it does not bound the first one.

Proposed work

Bring back caching for the parts of a compatible key ID lookup that do not depend on the purpose:

  • transport-level fetch failures, such as network errors and 404 Not Found, which fail every purpose alike;
  • possibly verified gateway keys under a cache key that only HTTP Signature verification reads, so that Linked Data Signatures and Object Integrity Proofs can never pick them up.

Design questions:

  • Is a purpose-scoped cache key enough, or should gateway keys get a separate KeyCache namespace?
  • How long should a verified gateway key be cached, given that it depends on the actor's signed document, which the actor may update to remove the gateway?
  • Should rejected portable actor documents, e.g., those without a valid proof, be cached as unavailable too?

Scope

This issue covers caching and its expiry only. The verification rules from #840 stay as they are.

Tests

  • repeated requests with an unreachable compatible key ID making one fetch within the cache lifetime;
  • a gateway key cached for HTTP Signatures not being accepted for a Linked Data Signature or an Object Integrity Proof with the same key ID;
  • a negative entry from one purpose not rejecting a valid key for another;
  • both HTTP Signature specifications, including the retry with a freshly fetched key.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Fields

Priority

None yet

Effort

None yet

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions