Skip to main content

agentd/auth/
mod.rs

1// SPDX-License-Identifier: AGPL-3.0-only
2//! Endpoint authentication — the interactive and workload credential providers
3//! and the token cache they share.
4//!
5//! Static headers (`mcp::auth`) and the AAuth request-signer (`aauth`) supply
6//! the `static` and `aauth` providers. This module owns the rest: the
7//! [`Kind::Cred`](crate::state::Kind::Cred)-backed [`cache`], the OAuth 2.1 /
8//! OIDC [`oauth2`] flows (device grant, browser + PKCE, refresh, discovery)
9//! behind `agentd login`, and the AWS SigV4 / IAM Identity Center providers.
10//! Everything but the cache is gated on the `oauth` cargo feature, so a build
11//! without it carries no interactive-login code at all.
12
13pub mod cache;
14
15#[cfg(feature = "oauth")]
16pub mod oauth2;
17
18#[cfg(feature = "oauth")]
19pub mod challenge;
20
21#[cfg(feature = "oauth")]
22pub mod login;
23
24#[cfg(feature = "oauth")]
25pub mod device;
26
27#[cfg(feature = "oauth")]
28pub mod aws;
29
30#[cfg(feature = "oauth")]
31pub mod aws_sso;
32
33#[cfg(feature = "oauth")]
34pub mod browser;
35
36/// Canonicalize a login/logout target: `mcp:<name>` on a server that references
37/// a service-catalog entry becomes `service:<entry>`, the key the daemon's
38/// connect path actually reads. Every server pointing at that entry shares one
39/// credential, so a login must land where all of them look and a logout must
40/// revoke it for all of them at once. Deliberately outside the `oauth` feature
41/// gate, so logout still resolves in a build without interactive login.
42pub fn canonical_target(settings: &crate::config::v2::Settings, target: &str) -> String {
43    if let Some(name) = target.strip_prefix("mcp:")
44        && let Some(svc) = settings
45            .mcp
46            .servers
47            .iter()
48            .find(|s| s.name == name)
49            .and_then(|s| s.service.clone())
50    {
51        return format!("service:{svc}");
52    }
53    target.to_string()
54}