pub struct OAuthAuthenticator<A> { /* private fields */ }Expand description
Authenticates bearer tokens against a TokenSource.
Generic over the source rather than holding a dyn, following
TokenSource’s own rule: the call site takes impl TokenSource, so this
monomorphises and the per-request cost is a direct call rather than a boxed
future behind a vtable. The scopes and the clock are dyn because a
deployment supplies them by value at construction and they are one call each.
Implementations§
Source§impl<A> OAuthAuthenticator<A>
impl<A> OAuthAuthenticator<A>
Sourcepub fn new(
source: A,
metadata: ResourceMetadata,
version: ProtocolVersion,
scopes: impl ScopePolicy + 'static,
clock: impl WallClock + 'static,
) -> Self
pub fn new( source: A, metadata: ResourceMetadata, version: ProtocolVersion, scopes: impl ScopePolicy + 'static, clock: impl WallClock + 'static, ) -> Self
An authenticator for source, protecting metadata’s resource under
the model version selects.
§Examples
use protocol_droid::adapters::primary::transport::http::{
OAuthAuthenticator, SystemClock,
};
use protocol_droid::application::oauth::NoScopes;
use protocol_droid::domain::{ProtocolVersion, mcp::{ResourceMetadata, ResourceUri}};
let metadata = ResourceMetadata::new(ResourceUri::new("https://example.com/mcp")?);
let authenticator = OAuthAuthenticator::new(
(), // a real deployment passes a `TokenSource`
metadata,
ProtocolVersion::V2025_06_18,
NoScopes,
SystemClock,
);Sourcepub fn with_expected_issuer(self, issuer: impl Into<Arc<str>>) -> Self
pub fn with_expected_issuer(self, issuer: impl Into<Arc<str>>) -> Self
Requires tokens to name issuer, rather than accepting any.
Off by default because RFC 9728 publishes a list of authorization servers this resource trusts, so a deployment fronted by more than one legitimately accepts more than one issuer. Turning it on is how a single-issuer deployment says so.
Sourcepub fn metadata(&self) -> &ResourceMetadata
pub fn metadata(&self) -> &ResourceMetadata
The resource this authenticator protects.
Trait Implementations§
Source§impl<A> Authenticator for OAuthAuthenticator<A>where
A: TokenSource,
impl<A> Authenticator for OAuthAuthenticator<A>where
A: TokenSource,
Source§fn authenticate<'a>(
&'a self,
presented: &'a Credentials<'_>,
) -> Pin<Box<dyn Future<Output = AuthContext> + Send + 'a>>
fn authenticate<'a>( &'a self, presented: &'a Credentials<'_>, ) -> Pin<Box<dyn Future<Output = AuthContext> + Send + 'a>>
presented is allowed to act under.Source§impl<A> Debug for OAuthAuthenticator<A>
impl<A> Debug for OAuthAuthenticator<A>
Source§fn fmt(&self, f: &mut Formatter<'_>) -> Result
fn fmt(&self, f: &mut Formatter<'_>) -> Result
Prints the configuration only.
Written by hand rather than derived, and not for the usual reason of a
field that is awkward to format: the derive would demand
A: Debug on the source — which for a JWT source would mean formatting
its key set — and dyn Debug on two fields that are behaviour, not
state. What is left is what an operator actually needs when a 401
shows up: which resource is protected, under which revision’s model,
and whether an issuer was pinned. The expected issuer is printed;
nothing else on this type is secret, and no token ever reaches it.