Skip to main content

topcoat_openapi/
security.rs

1use std::borrow::Cow;
2
3use serde::Serialize;
4
5/// A way for clients to authenticate, such as a bearer token or an API key.
6///
7/// Register it under a name with
8/// [`OpenApi::security_scheme`](crate::OpenApi::security_scheme), then
9/// require it with [`Operation::security`](crate::Operation::security):
10///
11/// ```
12/// use topcoat::openapi::{OpenApi, Operation, SecurityScheme};
13///
14/// let api = OpenApi::new("Acme API", "1.0.0")
15///     .security_scheme("token", SecurityScheme::bearer().bearer_format("JWT"));
16/// let operation = Operation::new().security("token");
17/// ```
18#[derive(Debug, Clone, Serialize)]
19#[serde(rename_all = "camelCase")]
20pub struct SecurityScheme {
21    #[serde(rename = "type")]
22    kind: &'static str,
23    #[serde(skip_serializing_if = "Option::is_none")]
24    description: Option<Cow<'static, str>>,
25    #[serde(skip_serializing_if = "Option::is_none")]
26    name: Option<Cow<'static, str>>,
27    #[serde(rename = "in", skip_serializing_if = "Option::is_none")]
28    location: Option<&'static str>,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    scheme: Option<&'static str>,
31    #[serde(skip_serializing_if = "Option::is_none")]
32    bearer_format: Option<Cow<'static, str>>,
33}
34
35impl SecurityScheme {
36    /// Creates a scheme that uses the HTTP `Authorization` header with the
37    /// given authentication scheme.
38    fn http(scheme: &'static str) -> Self {
39        Self {
40            kind: "http",
41            description: None,
42            name: None,
43            location: None,
44            scheme: Some(scheme),
45            bearer_format: None,
46        }
47    }
48
49    /// Creates a scheme that sends an API key under `name` in `location`.
50    fn api_key(location: &'static str, name: impl Into<Cow<'static, str>>) -> Self {
51        Self {
52            kind: "apiKey",
53            description: None,
54            name: Some(name.into()),
55            location: Some(location),
56            scheme: None,
57            bearer_format: None,
58        }
59    }
60
61    /// Authenticates with a token sent as `Authorization: Bearer <token>`.
62    #[must_use]
63    pub fn bearer() -> Self {
64        Self::http("bearer")
65    }
66
67    /// Authenticates with a user name and password sent through HTTP basic
68    /// authentication.
69    #[must_use]
70    pub fn basic() -> Self {
71        Self::http("basic")
72    }
73
74    /// Authenticates with an API key sent in the request header `name`.
75    #[must_use]
76    pub fn api_key_header(name: impl Into<Cow<'static, str>>) -> Self {
77        Self::api_key("header", name)
78    }
79
80    /// Authenticates with an API key sent as the query string key `name`.
81    #[must_use]
82    pub fn api_key_query(name: impl Into<Cow<'static, str>>) -> Self {
83        Self::api_key("query", name)
84    }
85
86    /// Authenticates with an API key sent in the cookie `name`.
87    #[must_use]
88    pub fn api_key_cookie(name: impl Into<Cow<'static, str>>) -> Self {
89        Self::api_key("cookie", name)
90    }
91
92    /// Explains how clients obtain and use the credentials.
93    #[must_use]
94    pub fn description(mut self, description: impl Into<Cow<'static, str>>) -> Self {
95        self.description = Some(description.into());
96        self
97    }
98
99    /// Names the format of a bearer token, such as `JWT`. This is a hint for
100    /// readers and only applies to a [`bearer`](Self::bearer) scheme.
101    #[must_use]
102    pub fn bearer_format(mut self, format: impl Into<Cow<'static, str>>) -> Self {
103        self.bearer_format = Some(format.into());
104        self
105    }
106}