pub enum AuthConfig {
None,
ApiKey {
query_params: HashMap<String, String>,
headers: HashMap<String, String>,
required: bool,
},
Bearer {
token: String,
required: bool,
},
Basic {
username: String,
password: String,
required: bool,
},
OAuth2ClientCredentials {
token_url: String,
client_id: String,
client_secret: String,
scopes: Vec<String>,
required: bool,
},
OAuthPassthrough {
target_header: String,
required: bool,
},
}Expand description
Outgoing-HTTP authentication configuration (OAPI-03 / D-05).
Lifted near-verbatim from the pmcp-run reference AuthConfig. The
#[serde(tag = "type", rename_all = "snake_case")] shape means a
config.toml [backend.auth] block selects the variant via type = "..."
(none, api_key, bearer, basic, oauth2_client_credentials,
oauth_passthrough). Default is AuthConfig::None.
Variants§
None
No authentication.
ApiKey
API key passed as query parameters and/or headers.
Fields
Bearer
Bearer token (Authorization: Bearer <token>).
Fields
Basic
HTTP Basic auth (Authorization: Basic <base64(user:pass)>).
Fields
username: StringUsername. Supports a ${VAR} / env:VAR reference (resolved at
provider-build time) for symmetry with password.
OAuth2ClientCredentials
OAuth2 client-credentials grant.
rename_all = "snake_case" derives the tag o_auth2_client_credentials,
but the documented config form (README, line-56 doc comment) is
type = "oauth2_client_credentials". The alias accepts the documented
spelling so [backend.auth] configs deserialize as documented.
Fields
OAuthPassthrough
Forward the INCOMING MCP client token to the backend (SSO passthrough, H1).
rename_all = "snake_case" derives the tag o_auth_passthrough, but the
documented config form (README, line-56 doc comment) is
type = "oauth_passthrough". The alias accepts the documented spelling so
[backend.auth] configs deserialize as documented.
Implementations§
Source§impl AuthConfig
impl AuthConfig
Sourcepub fn malformed_env_ref_field(&self) -> Option<String>
pub fn malformed_env_ref_field(&self) -> Option<String>
The first credential field whose configured value is REFERENCE-shaped but
names no settable environment variable, as a field path within
[backend.auth] (e.g. "token", "password", "query_params.app_key").
None when every credential field is a plain literal or a well-formed
single reference.
§Why this exists
crate::env_ref::parse_env_ref maps every unsettable brace form — the
empty ${}, a composition like ${A}://${B}, and a non-portable name
like ${TFL-APP-KEY} — to the EMPTY name. [resolve_secret_ref] then
resolves the empty name to the empty string, and the empty string is the
credential path’s “omit this credential” signal: [expand_api_key_map]
DROPS the entry and the bearer / basic / oauth2 arms of
create_auth_provider collapse to NoAuth. So a malformed reference
produced a server that booted fine and sent every backend request
UNAUTHENTICATED, with no error and no log line.
That omission rule is correct for an UNSET variable — an optional
credential the target environment chose not to supply — and it is
deliberately kept. A MALFORMED reference is a different thing: it is a
mistake in the config file that no environment could ever satisfy, so it
gets the refusal [backend].base_url already gets
(crate::error::ConfigValidationError::MalformedBackendBaseUrlRef).
The returned path names the FIELD only, never the value: a malformed value is by definition not a resolvable reference, so it may well be a mistyped literal secret that must not reach a log.
§Determinism
query_params / headers are HashMaps, so the offending entry is
selected by min over the keys rather than by iteration order — an
error message that named a different field run to run would be unusable.
§Examples
use pmcp_server_toolkit::http::auth::AuthConfig;
// A dash is not a portably settable variable name.
let bad = AuthConfig::Bearer { token: "${TFL-APP-KEY}".into(), required: true };
assert_eq!(bad.malformed_env_ref_field().as_deref(), Some("token"));
// A well-formed reference and a plain literal are both fine.
let good = AuthConfig::Bearer { token: "${TFL_APP_KEY}".into(), required: true };
assert_eq!(good.malformed_env_ref_field(), None);Sourcepub fn is_required(&self) -> bool
pub fn is_required(&self) -> bool
Whether this configuration requires authentication to succeed.
Trait Implementations§
Source§impl Clone for AuthConfig
impl Clone for AuthConfig
Source§impl Debug for AuthConfig
impl Debug for AuthConfig
Source§impl Default for AuthConfig
impl Default for AuthConfig
Source§impl<'de> Deserialize<'de> for AuthConfig
impl<'de> Deserialize<'de> for AuthConfig
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for AuthConfig
Source§impl PartialEq for AuthConfig
impl PartialEq for AuthConfig
Source§impl Serialize for AuthConfig
impl Serialize for AuthConfig
impl StructuralPartialEq for AuthConfig
Auto Trait Implementations§
impl Freeze for AuthConfig
impl RefUnwindSafe for AuthConfig
impl Send for AuthConfig
impl Sync for AuthConfig
impl Unpin for AuthConfig
impl UnsafeUnpin for AuthConfig
impl UnwindSafe for AuthConfig
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more