Skip to main content

AuthorizationServerMetadata

Struct AuthorizationServerMetadata 

Source
#[non_exhaustive]
pub struct AuthorizationServerMetadata {
Show 26 fields pub issuer: String, pub authorization_endpoint: String, pub token_endpoint: String, pub device_authorization_endpoint: String, pub introspection_endpoint: Option<String>, pub revocation_endpoint: Option<String>, pub registration_endpoint: Option<String>, pub jwks_uri: Option<String>, pub scopes_supported: Option<Vec<String>>, pub pushed_authorization_request_endpoint: Option<String>, pub require_pushed_authorization_requests: Option<bool>, pub request_object_signing_alg_values_supported: Option<Vec<String>>, pub require_signed_request_object: Option<bool>, pub response_types_supported: Vec<String>, pub response_modes_supported: Vec<String>, pub grant_types_supported: Vec<String>, pub token_endpoint_auth_methods_supported: Vec<String>, pub token_endpoint_auth_signing_alg_values_supported: Option<Vec<String>>, pub dpop_signing_alg_values_supported: Option<Vec<String>>, pub code_challenge_methods_supported: Vec<String>, pub service_documentation: Option<String>, pub protected_resources: Option<Vec<String>>, pub authorization_details_types_supported: Option<Vec<String>>, pub client_id_metadata_document_supported: bool, pub authorization_response_iss_parameter_supported: bool, pub tls_client_certificate_bound_access_tokens: bool,
}
Expand description

An RFC 8414 authorization server metadata document.

Optional members are Option and are OMITTED when absent, never serialized as null: RFC 8414 defines member types, and null is not one of them. #[non_exhaustive]: five features (par, jar, rar, mtls, resource-metadata) each add a member, which is what an RFC 8414 document IS: the list of what this build can do. A host builds this with AuthorizationServerMetadata::from_config, which is the only way to get a document that agrees with the server that will answer the requests it advertises; a literal written by hand is a document that describes a server nobody has to match. Deserialize is derived here and is unaffected, so a client-side or test-side consumer parsing one still works.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§issuer: String

REQUIRED (section 2). The AS’s issuer identifier; must equal the URL this document was retrieved from, minus the well-known path (section 3.3), and carries no query or fragment.

§authorization_endpoint: String

REQUIRED for an AS supporting the authorization code grant (section 2).

§token_endpoint: String

REQUIRED unless only the implicit grant is supported, which OAuth 2.1 removes (section 2).

§device_authorization_endpoint: String

RFC 8628 section 4: how an AS advertises device grant support.

§introspection_endpoint: Option<String>

RFC 7662 section 2. Present ONLY when the host named ServerConfig::introspection_endpoint, and absent otherwise.

§Why this one is opt-in and the others are not

RFC 7662’s primary consumer is a PROTECTED RESOURCE — the abstract defines the whole document as “a method for a protected resource to query an OAuth 2.0 authorization server”, and section 1 as a protocol that “allows authorized protected resources to query the authorization server”. Through 0.9.1 this server had no channel for one: it answered from a single arm, Some(t) if t.client_id == client.client_id, so a resource server that did what the document told it to do was told, indistinguishably from the truth, that every live token it held was dead. Advertising the endpoint unconditionally was therefore the exact thing this module’s opening rule forbids: an advertised capability the server rejects.

0.9.2 BUILT THE CHANNEL. A resource server declared in crate::ServerConfig::resource_servers now authenticates as an ordinary confidential client and is answered about the tokens addressed to it.

§Why this member stayed conditional anyway

0.9.1 recorded the intent that “when it lands this member becomes unconditional again”, and THAT INTENT IS DELIBERATELY NOT CARRIED OUT. Two reasons, and the second is the real one.

The cheap reason is that going back to String is itself a breaking change, so the API would take two breaking changes in consecutive releases to arrive where it started, and the second one would be paid by every host that had already adapted to the first.

The reason that actually decides it is that the capability is CONFIGURATION-DEPENDENT in a way 0.9.1 did not anticipate when it wrote that sentence. The resource-server channel is open only for a deployment that registered resource servers; one that registers none still answers the token’s own client and nobody else. Making the member unconditional would therefore restore the original defect precisely for the deployments the 0.9.1 change was made to protect – the endpoint would be advertised to resource servers that this particular deployment will never answer. The honest form of “advertise what you serve” is for the host, which is the only party that knows whether it configured any, to say so.

So: Option, and the host names the URL when it means the promise.

§revocation_endpoint: Option<String>

RFC 7009 section 2. Present when this server serves revocation.

§registration_endpoint: Option<String>

RFC 7591 section 3 / RFC 8414 section 2. Present ONLY when the host enabled dynamic client registration, and absent otherwise.

The conditional is the whole point of the member. RFC 8414 section 2 makes it optional, and a client reads its presence as “I may register here”; advertising it on a server that refuses every registration would be an endpoint that 404s or 401s for reasons a client cannot act on. The reverse is worse: RFC 7591 section 5 makes an unadvertised open endpoint no safer than an advertised one, so this must not become the thing a host relies on to keep registration private. It reports the configuration; it does not enforce it.

§jwks_uri: Option<String>

RFC 8414 section 2. With the jwt feature, present only when the server issues signed (JWT) access tokens; an AS with opaque tokens has no keys to publish and must not pretend otherwise.

WITHOUT that feature this crate signs nothing, so the member says only what crate::server::ServerConfig::jwks_uri said: some other component holds the keys and publishes them. Nothing in this crate serves that document, which is why the bundled http service refuses to build when such a value points UNDER the issuer, where its own router would answer the request with a 404.

§scopes_supported: Option<Vec<String>>

OPTIONAL (section 2). Omitted when the host has not declared a scope catalogue, since an empty array would claim the server supports no scopes at all.

§pushed_authorization_request_endpoint: Option<String>
Available on crate feature par only.

RFC 9126 section 5. Present ONLY when the host enabled PAR (crate::server::ServerConfig::par): section 5 says its presence is sufficient for a client to decide it may use PAR, so advertising an endpoint that is not served would be a promise this server cannot keep.

§require_pushed_authorization_requests: Option<bool>
Available on crate feature par only.

RFC 9126 section 5. Some(false) states the default explicitly when PAR is offered; omitted entirely when PAR is off, since section 5 gives an absent member the meaning false and a server with no PAR endpoint has nothing to require.

§request_object_signing_alg_values_supported: Option<Vec<String>>
Available on crate feature jar only.

RFC 9101 section 4: the alg values this server will verify a request object with. Present only when signed request objects are enabled.

§require_signed_request_object: Option<bool>
Available on crate feature jar only.

RFC 9101 section 10.5, registered by its section 9.2. Present only when signed request objects are enabled; true means a plain RFC 6749 authorization request is refused, which is the downgrade that section describes.

§response_types_supported: Vec<String>

REQUIRED (section 2). Always exactly ["code"]: OAuth 2.1 removes the implicit grant.

§response_modes_supported: Vec<String>

OPTIONAL (section 2). This server returns the code in the query string.

§grant_types_supported: Vec<String>

OPTIONAL (section 2), and worth stating: it is how a client learns the device grant is available without probing.

§token_endpoint_auth_methods_supported: Vec<String>

OPTIONAL (section 2). Exactly the methods the token endpoint accepts.

§token_endpoint_auth_signing_alg_values_supported: Option<Vec<String>>

RFC 8414 section 2. The signing algorithms the token endpoint accepts on an RFC 7523 client assertion.

Section 2 makes this REQUIRED whenever token_endpoint_auth_methods_supported contains client_secret_jwt or private_key_jwt, and the requirement is not bureaucratic: a client cannot construct an assertion at all without knowing which algorithm the server will accept, and guessing wrong is indistinguishable from a wrong key. Absent when this build does not have the client-assertion feature, in which case neither method is advertised either.

§dpop_signing_alg_values_supported: Option<Vec<String>>

RFC 9449 section 5.1: the JWS algorithms this server will verify a DPoP proof under.

Its PRESENCE is how a client learns DPoP is available here at all, so it appears only when this build can actually verify a proof. Advertising it on a server that would refuse every proof is worse than omitting it, because a client that acts on it has no way to discover the mistake except by failing to get a token.

§code_challenge_methods_supported: Vec<String>

RFC 7636 / RFC 8414 section 2. Always exactly ["S256"]: plain is not implemented, and advertising it would invite a downgrade this server cannot honor.

§service_documentation: Option<String>

OPTIONAL (section 2). A page of human-readable developer documentation.

§protected_resources: Option<Vec<String>>
Available on crate feature resource-metadata only.

RFC 9728 section 4. The resource identifiers of the protected resources this AS issues tokens for, so a client that fetched a resource’s own RFC 9728 document can cross-check that the AS agrees the relationship exists (section 7.6: an authorization_servers entry is a claim made by the RESOURCE, and believing it unchecked is how a resource points clients at an AS that never heard of it).

OPTIONAL, and omitted rather than empty when the host declared none: an empty array would state that this AS protects nothing, which is a different claim from silence.

§authorization_details_types_supported: Option<Vec<String>>
Available on crate feature rar only.

RFC 9396 section 10. The authorization details TYPES this server will accept, so a client learns what it may ask for rather than discovering it from a refusal.

Omitted rather than empty when the host declared none, exactly as scopes_supported is: an empty array claims the server supports no types at all, which is a different statement from silence and would be read as one. Note that the SERVER’s behaviour for the two is not different: an undeclared catalogue refuses every type (section 5), so this member never overstates what the server will do.

§client_id_metadata_document_supported: bool
Available on crate feature cimd only.

draft-ietf-oauth-client-id-metadata-document-01 section 5 (section 6 in -02; see crate::cimd for the renumbering). Whether this server dereferences an HTTPS URL used as a client_id.

DERIVED FROM ServerConfig::cimd, never from the cargo feature. The feature compiles the VALIDATOR in; it does not perform the fetch, because this crate performs no fetch at all (see crate::cimd). So the only party who can answer this honestly is the host that either wired the fetch or did not, and a member derived from #[cfg] would advertise a capability a build might always refuse. Section 5’s default when the member is absent is false, and this publishes false explicitly rather than omitting it, because the member is what a client checks before trying at all.

§authorization_response_iss_parameter_supported: bool

RFC 9207 section 3. Always true from this server, and NOT an Option.

The member exists so a client can decide whether it is allowed to REQUIRE the iss authorization response parameter, which is the mix-up countermeasure RFC 9700 section 4.4 names. RFC 9207 section 3 says its default when absent is false, so omitting it would tell every client that the countermeasure is unavailable here even though this server always sends the parameter. Publishing a constant true is only honest because crate::authorization::AuthorizationResponse and crate::authorization::AuthorizationErrorRedirect both carry iss unconditionally: the claim and the behaviour cannot drift apart, because neither type can express its absence.

RFC 8707 (resource indicators), which this server also implements, registers NO metadata member of its own, so there is deliberately nothing here to advertise it.

#[serde(default)] on the way IN, and it is not a contradiction of the constant true on the way out. Serialization is this server describing itself; deserialization is this type reading someone else’s document, and section 3 makes the member OPTIONAL there with a default of false. Without the attribute a bool field is a REQUIRED member to serde, so this type could not parse the document of any AS that omits it, which is every AS that does not implement RFC 9207. false is also the fail-closed reading: a client that cannot see the promise must not require the parameter.

§tls_client_certificate_bound_access_tokens: bool
Available on crate feature mtls only.

RFC 8705 section 3.3. Always true in a build with the mtls feature, and absent entirely without it, which is the same honesty rule jwks_uri follows.

Constant rather than configurable because the CODE PATH is: with the feature compiled in, an access token issued for a request whose certificate the host passed in through crate::server::ClientCredential::certificate is ALWAYS bound to it (RFC 8705 section 3). There is no ServerConfig field that turns that off. Section 3.3’s default when the member is absent is false, so a build without the feature says nothing and means nothing, which is correct.

READ WHAT THE MEMBER THEREFORE MEANS, because it is narrower than it looks and the gap is reachable. It says this server BINDS a certificate it is given; it does not and cannot say that every token this deployment issues is bound, because whether a certificate arrives at all is the host’s affair. This crate never terminates TLS. In particular the bundled http feature’s router is handed an already-parsed request and passes certificate: None on every credential it builds (see the comment on Credentials::credential in crate::http), so a deployment whose only front door is that router publishes true here and binds nothing. A host offering RFC 8705 has to reach the server through its own handler with the certificate its terminator verified; a host that is not doing that should not compile the mtls feature in, because this member is the promise a client acts on when it decides to present one.

#[serde(default)] for the reason its neighbour above carries one, and the case is not hypothetical here: a build WITHOUT this feature omits the member entirely, so an mtls build reading a non-mtls build’s own document failed outright with missing field "tls_client_certificate_bound_access_tokens" until 0.9.1. Section 3.3’s absent-means-false is both the RFC’s answer and the fail-closed one: a client that cannot see the promise must not assume its token is bound.

Implementations§

Source§

impl AuthorizationServerMetadata

Source

pub fn from_config(config: &ServerConfig) -> Self

Derive the document from the server’s configuration.

Endpoints the host did not override default to conventional paths under the issuer, so a host that configures only an issuer still publishes a coherent, self-consistent document.

Trait Implementations§

Source§

impl Clone for AuthorizationServerMetadata

Source§

fn clone(&self) -> AuthorizationServerMetadata

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for AuthorizationServerMetadata

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for AuthorizationServerMetadata

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Eq for AuthorizationServerMetadata

Source§

impl PartialEq for AuthorizationServerMetadata

Source§

fn eq(&self, other: &AuthorizationServerMetadata) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for AuthorizationServerMetadata

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for AuthorizationServerMetadata

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.