Expand description
The outbound endpoint guard for the one OAuth generation (hand-authored, user-owned).
Why this file exists: the upstream code this module replaces guarded its
outbound OAuth calls with a debug assert over a host allowlist — an
assertion the runtime strips under optimization, and whose Microsoft
endpoints were overridable at runtime with no validation at all. The guard
here is a real one, and it fails closed at every layer:
- Registry (compile time) —
ProviderRegistrycarries the adapter data for every supported provider: endpoint URLs, default scopes, the PKCE capability, and the host allowlist for that provider family. There is no code path that constructs a provider URL from anything a request supplied. - Validation (config-load time) — every endpoint override arriving
from configuration passes
validate_endpointbefore the module using it may build: https-only, host suffix-matched against the provider’s allowlist, no userinfo component, no IP-literal host, no port other than 443, a non-root path, no query, no fragment. ANY violation is anInvalidEndpointand the module builder refuses to build — a bad override yields no module, not a degraded one. - Re-validation (request time) — a
ValidatedEndpointcan only be constructed through validation, and the transport re-runs the full rule set (ValidatedEndpoint::revalidate) before every call, so an endpoint that reached the transport by internal drift is refused there too. Fail closed at build time AND at request time. - Resolution guard (transport time) — the reqwest client follows no
redirects (
reqwest::redirect::Policy::none) and resolves the host before connecting, refusing loopback/private/link-local/unique-local addresses (assert_public_resolution) — a basic DNS-rebinding closure on top of the allowlist.
The type system carries the guarantee: the transport accepts ONLY
ValidatedEndpoint values — “URL that passed the guard” is the sole
currency — and the field inside is private, so no caller can smuggle an
unvalidated URL into an outbound call.
OAuthTransport is the port the OAuth flow and the refresh scheduler
share; tests inject a fake that records every URL it was handed.
Structs§
- Endpoint
Overrides - The
oauth.endpointsconfiguration section: provider key → overrides. - Identity
Claims - The verified identity of the token’s subject, as read server-side (the
userinfo endpoint, or the id_token the token endpoint returned — never a
browser-side claim).
audienceandnoncecarry the id_token’s values so the flow can enforce the audience check and the nonce binding. - Invalid
Endpoint - A configuration-time endpoint rejection. Fail closed: the caller building the module refuses to proceed.
- OAuth
Client Config - One provider’s OAuth client registration. The client id is not a secret (it travels in the authorize URL); the client secret is — redacted in Debug, zeroized on drop.
- OAuth
Client Configs - The
oauth.clientsconfiguration section: provider key → client config. - Provider
Adapter - One provider’s adapter data: the endpoints, default scopes, PKCE
capability, and host allowlist. Purely compile-time — per-deployment
overrides arrive through
EndpointOverridesand are validated against the allowlist here before use. - Provider
Endpoint Override - Per-provider endpoint overrides from configuration. Empty by default — no override means the registry value. An override is a candidate, never a truth: it is validated before use, and a bad one fails the build.
- Provider
Registry - The compile-time provider registry.
ProviderRegistry::with_builtincarries the four OAuth providers; composition may add adapters, never remove the validation contract. - ReqwestO
Auth Transport - The production
OAuthTransport: a reqwest client that follows no redirects, carries explicit timeouts, re-validates the endpoint before every call, and resolves the host through the private-range guard before connecting. - Token
Request Form - An OAuth token-endpoint request form (code exchange or refresh grant),
serialized as
application/x-www-form-urlencoded. Debug is redacted — the code, refresh token, and client secret must never drift into a log line. - Token
Response - A provider token response.
expires_inmissing means the provider claims no expiry — per the honest-lifetime rule such a response is UNSTOREABLE and callers refuse it (a “permanent” token is not a value the flow will store). Debug is redacted. - Transport
Failure - Validated
Endpoint - A URL that passed the full rule set. Constructible only through
validate_endpoint(the inner URL is private); the transport accepts nothing else, and re-runs the rules before every call. - Validated
Endpoints - A provider’s three endpoints, resolved and validated. Produced by
ValidatedEndpoints::resolve— registry values by default, validated overrides where present. The sole endpoint currency the OAuth flow and the refresh scheduler deal in.
Enums§
- Endpoint
Key - Which of a provider’s three endpoints a URL is being validated as.
- Transport
Failure Kind - Why an outbound OAuth call failed.
Constants§
- GOOGLE_
HOSTS - The host allowlist for the Google provider family. A configured endpoint
for
gmail/google_calendarmay live ONLY on these hosts (exact match or a subdomain of a listed host). - MICROSOFT_
HOSTS - The host allowlist for the Microsoft provider family (
outlook/microsoft_calendar). - OAUTH_
CONNECT_ TIMEOUT - Default connect budget for one outbound OAuth call.
- OAUTH_
REQUEST_ TIMEOUT - Default total budget for one outbound OAuth call.
- PROVIDER_
GMAIL - Provider key constants (the
OAuthProviderenum’s values as plain strings, so infrastructure stays independent of the generated entity enum). - PROVIDER_
GOOGLE_ CALENDAR - PROVIDER_
MICROSOFT_ CALENDAR - PROVIDER_
OUTLOOK
Traits§
- OAuth
Transport - The outbound transport port: token exchange and server-side identity fetch. Both methods take ONLY validated endpoints — an unvalidated URL cannot reach the network through this trait.
Functions§
- assert_
public_ resolution - Resolve
hostand refuse any answer in a forbidden range — the basic DNS-rebinding closure. The allowlist remains the primary control (an attacker cannot control DNS for an allowlisted provider host); this check bounds the residual window where a name that passed the allowlist resolves somewhere it should not. Returns the resolved addresses on success. - ip_
is_ public - Whether an address is acceptable as an outbound OAuth target: not loopback, not private (RFC1918 + carrier-grade NAT), not link-local, not unique-local (fc00::/7), not unspecified, not multicast — for IPv4, IPv6, and IPv4-mapped IPv6 alike.
- validate_
endpoint - Validate one endpoint URL against a provider’s host allowlist. The full rule set, in order: