Expand description
Fetching, validating, and caching OAuth client metadata documents.
atproto’s OAuth profile has no registered-client table: a client_id is
an HTTPS URL, and the document served there is the client’s
registration, fetched fresh (or from a short-lived cache) on every use.
plan/app-allowlist.md needs more than the URL to enforce “an app that
changes its redirect URIs is a different app” — so ClientKey is
computed over the validated document’s own content, not over the
client_id string, and it is what ClientMetadataCache keys on.
This module does not decide whether a client is admitted; it decides
whether a document is usable at all. Admission is
plan/app-allowlist.md’s hook, called from oauth::par once a validated
document exists.
One client_id form is the exception to “fetched fresh”: the atproto
profile’s “Localhost Client Development” client_id, exactly
http://localhost with no port and an empty or / path. There is
nothing to fetch — parse_loopback_client_id builds the document
straight from that URL’s own redirect_uri/scope query parameters, and
resolve_client returns it before ever reaching the network.
No other client_id may name a port: the profile says “there must not
be a port number included”. A development deployment reaches a client
serving on another port through didbot_identity::did::RESOLVE_PORTS,
as it reaches a did:web.
Structs§
- Cached
Client Metadata - A cached, validated document plus when it was fetched.
- Client
Key - A validated document’s own identity, for
ClientMetadataCacheand forplan/app-allowlist.md’s “an admitted app that changes its redirect URIs is a different app” — computed over the document’s content, so two fetches of the sameclient_idthat disagree produce two different keys. - Client
Metadata Document - A validated client metadata document.
- Memory
Client Metadata Cache - The in-process client metadata cache.
Enums§
- Application
Type - A document’s
application_type, which the atproto profile borrows from OpenID Connect. Absent, it isweb; any other word refuses the document. - Client
Metadata Error - Why a client metadata document could not be used.
- Loopback
Clients - Whether this deployment will fetch a client metadata document over
loopback
http://.
Constants§
- CACHE_
CAPACITY - How many distinct
client_idsMemoryClientMetadataCacheholds at once. - CACHE_
TTL - How long a fetched document is trusted before it is fetched again.
- FETCH_
TIMEOUT - How long the whole client metadata fetch may take — connect, headers and body together, not just the handshake.
- MAX_
DOCUMENT_ BYTES - The most of a client metadata document this server will read before giving up on it.
Traits§
- Client
Metadata Cache - Where fetched client metadata is cached, keyed by
client_id.
Functions§
- check_
authentication 🔒 - Refuses what the atproto profile’s “Confidential Client Authentication” refuses of a document’s client authentication fields.
- fetch_
bounded 🔒 - GETs
urlonclient_id’s behalf, under every boundresolve_clientnames:FETCH_TIMEOUTfor the whole fetch,MAX_DOCUMENT_BYTESfor the body, and no redirect. Only a200 OKis read, and whenjson_only, only one served asapplication/json. - fetch_
jwks 🔒 - The key set a confidential client publishes at
jwks_uri, fetched the way its document is (fetch_bounded). - is_
loopback_ 🔒redirect_ uri - Whether
rawis a usable loopback redirect URI:http://127.0.0.1orhttp://[::1], any port, per the atproto profile’s “Localhost Client Development” form. Stricter thandidbot_http::is_loopbackon purpose — that one also accepts the literal namelocalhost, which this form forbids for a redirect. - is_
native_ 🔒redirect_ uri - Whether a native client named
client_idmay registerrawas a redirect, by the atproto profile’s rules for native clients. - is_
web_ 🔒redirect_ uri - Whether a web client may register
rawas a redirect: the profile says a web client’s redirect “is a HTTPS URL”. A loopbackhttp://redirect belongs to a native client. - parse_
loopback_ 🔒client_ id - Recognises the atproto OAuth profile’s “Localhost Client Development”
client_idform — exactlyhttp://localhost, no port, path empty or/— and builds its virtual client metadata document straight from theredirect_uri(repeatable) andscopequery parameters, fetching nothing. - pinned_
public_ 🔒client - A client for fetching
url, pinned to the addresses its host resolves to, and refused unless every one of them is onedidbot_http::is_public_addressallows. - read_
bounded 🔒 - Reads at most
MAX_DOCUMENT_BYTESof a response body. - redirected_
away_ 🔒from - Where a response landed, if that is not
requested. - resolve_
client - Fetches, validates, and caches the client metadata document for
client_id. - same_
loopback_ 🔒redirect - Whether
requestedis the loopback redirectregistered, on any port. - validate
- Validates a raw fetched document against
client_id, the URL it was fetched from. - validate_
url_ 🔒scheme - Checks a URL is
https://(or loopbackhttp://) with no fragment.