openapiv3/
security_scheme.rs

1use indexmap::IndexMap;
2use serde::{Deserialize, Serialize};
3
4/// Defines a security scheme that can be used by the operations.
5/// Supported schemes are HTTP authentication, an API key (either as a
6/// header or as a query parameter), OAuth2's common flows (implicit, password,
7/// application and access code) as defined in RFC6749, and OpenID Connect Discovery.
8#[allow(clippy::large_enum_variant)]
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
10#[serde(tag = "type")]
11pub enum SecurityScheme {
12    #[serde(rename = "apiKey")]
13    APIKey {
14        /// The location of the API key. Valid values are "query", "header" or
15        /// "cookie".
16        #[serde(rename = "in")]
17        location: APIKeyLocation,
18        /// The name of the header, query or cookie parameter to be used.
19        name: String,
20        /// A short description for security scheme. CommonMark syntax MAY be
21        /// used for rich text representation.
22        #[serde(skip_serializing_if = "Option::is_none")]
23        description: Option<String>,
24
25        /// Inline extensions to this object.
26        #[serde(flatten, deserialize_with = "crate::util::deserialize_extensions")]
27        extensions: IndexMap<String, serde_json::Value>,
28    },
29    #[serde(rename = "http")]
30    HTTP {
31        /// The name of the HTTP Authorization scheme to be used in the
32        /// Authorization header as defined in RFC7235. The values used SHOULD
33        /// be registered in the IANA Authentication Scheme registry.
34        scheme: String,
35        #[serde(rename = "bearerFormat", skip_serializing_if = "Option::is_none")]
36        bearer_format: Option<String>,
37        /// A short description for security scheme. CommonMark syntax MAY be
38        /// used for rich text representation.
39        #[serde(skip_serializing_if = "Option::is_none")]
40        description: Option<String>,
41
42        /// Inline extensions to this object.
43        #[serde(flatten, deserialize_with = "crate::util::deserialize_extensions")]
44        extensions: IndexMap<String, serde_json::Value>,
45    },
46    #[serde(rename = "oauth2")]
47    OAuth2 {
48        /// An object containing configuration information for the flow types
49        /// supported.
50        flows: OAuth2Flows,
51        /// A short description for security scheme. CommonMark syntax MAY be
52        /// used for rich text representation.
53        #[serde(skip_serializing_if = "Option::is_none")]
54        description: Option<String>,
55
56        /// Inline extensions to this object.
57        #[serde(flatten, deserialize_with = "crate::util::deserialize_extensions")]
58        extensions: IndexMap<String, serde_json::Value>,
59    },
60    #[serde(rename = "openIdConnect")]
61    OpenIDConnect {
62        /// OpenId Connect URL to discover OAuth2 configuration values. This
63        /// MUST be in the form of a URL.
64        #[serde(rename = "openIdConnectUrl")]
65        open_id_connect_url: String,
66        /// A short description for security scheme. CommonMark syntax MAY be
67        /// used for rich text representation.
68        #[serde(skip_serializing_if = "Option::is_none")]
69        description: Option<String>,
70
71        /// Inline extensions to this object.
72        #[serde(flatten, deserialize_with = "crate::util::deserialize_extensions")]
73        extensions: IndexMap<String, serde_json::Value>,
74    },
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
78#[serde(rename_all = "camelCase")]
79pub enum APIKeyLocation {
80    Query,
81    Header,
82    Cookie,
83}
84
85#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
86#[serde(rename_all = "camelCase")]
87pub struct OAuth2Flows {
88    /// Configuration for the OAuth Implicit flow
89    #[serde(default, skip_serializing_if = "Option::is_none")]
90    pub implicit: Option<ImplicitOAuth2Flow>,
91    /// Configuration for the OAuth Resource Owner Password flow
92    #[serde(default, skip_serializing_if = "Option::is_none")]
93    pub password: Option<PasswordOAuth2Flow>,
94    /// Configuration for the OAuth Client Credentials flow.
95    #[serde(default, skip_serializing_if = "Option::is_none")]
96    pub client_credentials: Option<ClientCredentialsOAuth2Flow>,
97    /// Configuration for the OAuth Authorization Code flow.
98    #[serde(default, skip_serializing_if = "Option::is_none")]
99    pub authorization_code: Option<AuthorizationCodeOAuth2Flow>,
100
101    /// Inline extensions to this object.
102    #[serde(flatten, deserialize_with = "crate::util::deserialize_extensions")]
103    pub extensions: IndexMap<String, serde_json::Value>,
104}
105#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
106#[serde(rename_all = "camelCase")]
107pub struct ImplicitOAuth2Flow {
108    /// The authorization URL to be used for this flow. This MUST be in the
109    /// form of a URL.
110    authorization_url: String,
111    /// The URL to be used for obtaining refresh tokens. This MUST be in the
112    /// form of a URL.
113    #[serde(skip_serializing_if = "Option::is_none")]
114    refresh_url: Option<String>,
115    /// The available scopes for the OAuth2 security scheme. A map between the
116    /// scope name and a short description for it. The map MAY be empty.
117    scopes: IndexMap<String, String>,
118
119    /// Inline extensions to this object.
120    #[serde(flatten, deserialize_with = "crate::util::deserialize_extensions")]
121    pub extensions: IndexMap<String, serde_json::Value>,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
125#[serde(rename_all = "camelCase")]
126pub struct PasswordOAuth2Flow {
127    /// The URL to be used for obtaining refresh tokens. This MUST be in the
128    /// form of a URL.
129    #[serde(skip_serializing_if = "Option::is_none")]
130    refresh_url: Option<String>,
131    /// The token URL to be used for this flow. This MUST be in the form of a
132    /// URL.
133    token_url: String,
134    /// The available scopes for the OAuth2 security scheme. A map between the
135    /// scope name and a short description for it. The map MAY be empty.
136    scopes: IndexMap<String, String>,
137
138    /// Inline extensions to this object.
139    #[serde(flatten, deserialize_with = "crate::util::deserialize_extensions")]
140    pub extensions: IndexMap<String, serde_json::Value>,
141}
142#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
143#[serde(rename_all = "camelCase")]
144pub struct ClientCredentialsOAuth2Flow {
145    /// The URL to be used for obtaining refresh tokens. This MUST be in the
146    /// form of a URL.
147    #[serde(skip_serializing_if = "Option::is_none")]
148    refresh_url: Option<String>,
149    /// The token URL to be used for this flow. This MUST be in the form of a
150    /// URL.
151    token_url: String,
152    /// The available scopes for the OAuth2 security scheme. A map between the
153    /// scope name and a short description for it. The map MAY be empty.
154    scopes: IndexMap<String, String>,
155
156    /// Inline extensions to this object.
157    #[serde(flatten, deserialize_with = "crate::util::deserialize_extensions")]
158    pub extensions: IndexMap<String, serde_json::Value>,
159}
160
161#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
162#[serde(rename_all = "camelCase")]
163pub struct AuthorizationCodeOAuth2Flow {
164    /// The authorization URL to be used for this flow. This MUST be in the
165    /// form of a URL.
166    authorization_url: String,
167    /// The token URL to be used for this flow. This MUST be in the form of a
168    /// URL.
169    token_url: String,
170    /// The URL to be used for obtaining refresh tokens. This MUST be in the
171    /// form of a URL.
172    #[serde(skip_serializing_if = "Option::is_none")]
173    refresh_url: Option<String>,
174    /// The available scopes for the OAuth2 security scheme. A map between the
175    /// scope name and a short description for it. The map MAY be empty.
176    scopes: IndexMap<String, String>,
177
178    /// Inline extensions to this object.
179    #[serde(flatten, deserialize_with = "crate::util::deserialize_extensions")]
180    pub extensions: IndexMap<String, serde_json::Value>,
181}
182
183#[cfg(test)]
184mod tests {
185    use crate::{OpenAPI, ReferenceOr, SecurityScheme};
186
187    #[test]
188    fn test_slack_auth() {
189        let openapi: OpenAPI =
190            serde_json::from_reader(std::fs::File::open("fixtures/slack.json").unwrap()).unwrap();
191
192        assert!(matches!(
193            openapi
194                .components
195                .as_ref()
196                .unwrap()
197                .security_schemes
198                .get("slackAuth")
199                .unwrap(),
200            ReferenceOr::Item(SecurityScheme::OAuth2 { .. })
201        ));
202    }
203}