Skip to main content

systemprompt_models/a2a/
security.rs

1//! `A2A` security scheme definitions (API key, HTTP, `OAuth2`) for agent card
2//! auth.
3//!
4//! Copyright (c) systemprompt.io — Business Source License 1.1.
5//! See <https://systemprompt.io> for licensing details.
6
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
11#[serde(tag = "type", rename_all = "camelCase")]
12pub enum SecurityScheme {
13    #[serde(rename = "apiKey")]
14    ApiKey {
15        name: String,
16        #[serde(rename = "in")]
17        location: ApiKeyLocation,
18        description: Option<String>,
19    },
20    #[serde(rename = "http")]
21    Http {
22        scheme: String,
23        bearer_format: Option<String>,
24        description: Option<String>,
25    },
26    #[serde(rename = "oauth2")]
27    OAuth2 {
28        flows: Box<OAuth2Flows>,
29        description: Option<String>,
30    },
31    #[serde(rename = "openIdConnect")]
32    OpenIdConnect {
33        open_id_connect_url: String,
34        description: Option<String>,
35    },
36    #[serde(rename = "mutualTLS")]
37    MutualTls { description: Option<String> },
38}
39
40#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
41#[serde(rename_all = "camelCase")]
42pub enum ApiKeyLocation {
43    Query,
44    Header,
45    Cookie,
46}
47
48impl std::fmt::Display for ApiKeyLocation {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        match self {
51            Self::Query => write!(f, "query"),
52            Self::Header => write!(f, "header"),
53            Self::Cookie => write!(f, "cookie"),
54        }
55    }
56}
57
58impl std::str::FromStr for ApiKeyLocation {
59    type Err = String;
60
61    fn from_str(s: &str) -> Result<Self, Self::Err> {
62        match s {
63            "query" => Ok(Self::Query),
64            "header" => Ok(Self::Header),
65            "cookie" => Ok(Self::Cookie),
66            _ => Err(format!("Invalid API key location: {s}")),
67        }
68    }
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
72#[serde(rename_all = "camelCase")]
73pub struct OAuth2Flows {
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub implicit: Option<OAuth2Flow>,
76    #[serde(skip_serializing_if = "Option::is_none")]
77    pub password: Option<OAuth2Flow>,
78    #[serde(skip_serializing_if = "Option::is_none")]
79    pub client_credentials: Option<OAuth2Flow>,
80    #[serde(skip_serializing_if = "Option::is_none")]
81    pub authorization_code: Option<OAuth2Flow>,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
85#[serde(rename_all = "camelCase")]
86pub struct OAuth2Flow {
87    pub authorization_url: Option<String>,
88    pub token_url: Option<String>,
89    pub refresh_url: Option<String>,
90    pub scopes: HashMap<String, String>,
91}
92
93pub type AgentAuthentication = serde_json::Value;