Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ wiremock = { git = "https://github.com/howardjohn/wiremock-rs", rev = "e55f5b960
[workspace]
resolver = "2"
members = [
"crates/aauth",
"crates/agentgateway",
"crates/agentgateway-app",
"crates/cel-fork/cel",
"crates/cel-fork/cel-derive",
"crates/celx",
"crates/http-message-sig",
"crates/pool",
"crates/core",
"crates/hbone",
Expand All @@ -19,11 +21,13 @@ members = [
"crates/xtask",
]
default-members = [
"crates/aauth",
"crates/agentgateway",
"crates/agentgateway-app",
"crates/cel-fork/cel",
"crates/cel-fork/cel-derive",
"crates/celx",
"crates/http-message-sig",
"crates/pool",
"crates/core",
"crates/hbone",
Expand All @@ -39,6 +43,7 @@ license = "Apache-2.0"
publish = false

[workspace.dependencies]
aauth = { path = "crates/aauth" }
agent-core = { path = "crates/core" }
agent-celx = { path = "crates/celx" }
agent-hbone = { path = "crates/hbone" }
Expand All @@ -47,6 +52,7 @@ agent-xds = { path = "crates/xds" }
agentgateway = { path = "crates/agentgateway" }
cel = { path = "crates/cel-fork/cel" }
cel-derive = { path = "crates/cel-fork/cel-derive" }
http-message-sig = { path = "crates/http-message-sig" }
protos = { path = "crates/protos" }
atomic_float = { version = "1.1.0", features = ["serde"] }
anyhow = "1.0"
Expand Down
15 changes: 15 additions & 0 deletions crates/aauth/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "aauth"
version.workspace = true
edition.workspace = true
license.workspace = true
publish.workspace = true

[dependencies]
base64.workspace = true
http-message-sig.workspace = true
jsonwebtoken.workspace = true
serde.workspace = true
serde_json.workspace = true
thiserror.workspace = true
url.workspace = true
30 changes: 30 additions & 0 deletions crates/aauth/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use thiserror::Error;

/// Errors from AAuth token validation.
///
/// Errors from the underlying HTTP signing layer are forwarded transparently via `#[from]` on
/// [`http_message_sig::Error`]. Callers wanting to react to a specific signing error should match
/// on the embedded variant rather than parsing the display string.
#[derive(Debug, Error)]
pub enum AAuthError {
#[error("HTTP signing error: {0}")]
Signing(#[from] http_message_sig::Error),

#[error("failed to fetch JWKS: {0}")]
JwksFetch(String),

#[error("JWT validation failed: {0}")]
JwtValidation(String),

#[error("audience mismatch")]
AudienceMismatch,

#[error("missing required claim: {0}")]
MissingClaim(String),

#[error("invalid issuer URL: must be HTTPS with host only (no port, path, query, or fragment)")]
InvalidIssuerUrl,

#[error("act.sub claim does not match agent identifier")]
ActClaimMismatch,
}
9 changes: 9 additions & 0 deletions crates/aauth/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! AAuth protocol token validation (draft-hardt-oauth-aauth-protocol).
//!
//! This crate implements AAuth agent and auth token validation. The underlying HTTP signing layer
//! (RFC 9421 plus the HTTP Signature Keys draft) lives in [`http_message_sig`].
pub mod errors;
pub mod tokens;

pub use errors::AAuthError;
Loading
Loading