Skip to main content

Module endpoint_guard

Module endpoint_guard 

Source
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:

  1. Registry (compile time) — ProviderRegistry carries 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.
  2. Validation (config-load time) — every endpoint override arriving from configuration passes validate_endpoint before 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 an InvalidEndpoint and the module builder refuses to build — a bad override yields no module, not a degraded one.
  3. Re-validation (request time) — a ValidatedEndpoint can 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.
  4. 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§

EndpointOverrides
The oauth.endpoints configuration section: provider key → overrides.
IdentityClaims
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). audience and nonce carry the id_token’s values so the flow can enforce the audience check and the nonce binding.
InvalidEndpoint
A configuration-time endpoint rejection. Fail closed: the caller building the module refuses to proceed.
OAuthClientConfig
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.
OAuthClientConfigs
The oauth.clients configuration section: provider key → client config.
ProviderAdapter
One provider’s adapter data: the endpoints, default scopes, PKCE capability, and host allowlist. Purely compile-time — per-deployment overrides arrive through EndpointOverrides and are validated against the allowlist here before use.
ProviderEndpointOverride
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.
ProviderRegistry
The compile-time provider registry. ProviderRegistry::with_builtin carries the four OAuth providers; composition may add adapters, never remove the validation contract.
ReqwestOAuthTransport
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.
TokenRequestForm
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.
TokenResponse
A provider token response. expires_in missing 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.
TransportFailure
ValidatedEndpoint
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.
ValidatedEndpoints
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§

EndpointKey
Which of a provider’s three endpoints a URL is being validated as.
TransportFailureKind
Why an outbound OAuth call failed.

Constants§

GOOGLE_HOSTS
The host allowlist for the Google provider family. A configured endpoint for gmail / google_calendar may 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 OAuthProvider enum’s values as plain strings, so infrastructure stays independent of the generated entity enum).
PROVIDER_GOOGLE_CALENDAR
PROVIDER_MICROSOFT_CALENDAR
PROVIDER_OUTLOOK

Traits§

OAuthTransport
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 host and 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: