rusttls_jwt_authorizer/
builder.rs

1use std::sync::Arc;
2
3use serde::de::DeserializeOwned;
4
5use crate::{
6    authorizer::{ClaimsCheckerFn, KeySourceType},
7    error::InitError,
8    layer::{AuthorizationLayer, JwtSource},
9    Authorizer, Refresh, RefreshStrategy, RegisteredClaims, Validation,
10};
11
12use reqwest::Client;
13
14/// Authorizer Layer builder
15///
16/// - initialisation of the Authorizer from jwks, rsa, ed, ec or secret
17/// - can define a checker (jwt claims check)
18pub struct AuthorizerBuilder<C = RegisteredClaims>
19where
20    C: Clone + DeserializeOwned,
21{
22    key_source_type: KeySourceType,
23    refresh: Option<Refresh>,
24    claims_checker: Option<ClaimsCheckerFn<C>>,
25    validation: Option<Validation>,
26    jwt_source: JwtSource,
27    http_client: Option<Client>,
28}
29
30/// alias for AuthorizerBuidler (backwards compatibility)
31pub type JwtAuthorizer<C = RegisteredClaims> = AuthorizerBuilder<C>;
32
33/// authorization layer builder
34impl<C> AuthorizerBuilder<C>
35where
36    C: Clone + DeserializeOwned + Send + Sync,
37{
38    /// Builds Authorizer Layer from a OpenId Connect discover metadata
39    pub fn from_oidc(issuer: &str) -> AuthorizerBuilder<C> {
40        AuthorizerBuilder {
41            key_source_type: KeySourceType::Discovery(issuer.to_string()),
42            refresh: Default::default(),
43            claims_checker: None,
44            validation: None,
45            jwt_source: JwtSource::AuthorizationHeader,
46            http_client: None,
47        }
48    }
49
50    /// Builds Authorizer Layer from a JWKS endpoint
51    pub fn from_jwks_url(url: &str) -> AuthorizerBuilder<C> {
52        AuthorizerBuilder {
53            key_source_type: KeySourceType::Jwks(url.to_owned()),
54            refresh: Default::default(),
55            claims_checker: None,
56            validation: None,
57            jwt_source: JwtSource::AuthorizationHeader,
58            http_client: None,
59        }
60    }
61
62    pub fn from_jwks(path: &str) -> AuthorizerBuilder<C> {
63        AuthorizerBuilder {
64            key_source_type: KeySourceType::JwksPath(path.to_owned()),
65            refresh: Default::default(),
66            claims_checker: None,
67            validation: None,
68            jwt_source: JwtSource::AuthorizationHeader,
69            http_client: None,
70        }
71    }
72
73    pub fn from_jwks_text(text: &str) -> AuthorizerBuilder<C> {
74        AuthorizerBuilder {
75            key_source_type: KeySourceType::JwksString(text.to_owned()),
76            refresh: Default::default(),
77            claims_checker: None,
78            validation: None,
79            jwt_source: JwtSource::AuthorizationHeader,
80            http_client: None,
81        }
82    }
83
84    /// Builds Authorizer Layer from a RSA PEM file
85    pub fn from_rsa_pem(path: &str) -> AuthorizerBuilder<C> {
86        AuthorizerBuilder {
87            key_source_type: KeySourceType::RSA(path.to_owned()),
88            refresh: Default::default(),
89            claims_checker: None,
90            validation: None,
91            jwt_source: JwtSource::AuthorizationHeader,
92            http_client: None,
93        }
94    }
95
96    /// Builds Authorizer Layer from an RSA PEM raw text
97    pub fn from_rsa_pem_text(text: &str) -> AuthorizerBuilder<C> {
98        AuthorizerBuilder {
99            key_source_type: KeySourceType::RSAString(text.to_owned()),
100            refresh: Default::default(),
101            claims_checker: None,
102            validation: None,
103            jwt_source: JwtSource::AuthorizationHeader,
104            http_client: None,
105        }
106    }
107
108    /// Builds Authorizer Layer from a EC PEM file
109    pub fn from_ec_pem(path: &str) -> AuthorizerBuilder<C> {
110        AuthorizerBuilder {
111            key_source_type: KeySourceType::EC(path.to_owned()),
112            refresh: Default::default(),
113            claims_checker: None,
114            validation: None,
115            jwt_source: JwtSource::AuthorizationHeader,
116            http_client: None,
117        }
118    }
119
120    /// Builds Authorizer Layer from a EC PEM raw text
121    pub fn from_ec_pem_text(text: &str) -> AuthorizerBuilder<C> {
122        AuthorizerBuilder {
123            key_source_type: KeySourceType::ECString(text.to_owned()),
124            refresh: Default::default(),
125            claims_checker: None,
126            validation: None,
127            jwt_source: JwtSource::AuthorizationHeader,
128            http_client: None,
129        }
130    }
131
132    /// Builds Authorizer Layer from a EC PEM file
133    pub fn from_ed_pem(path: &str) -> AuthorizerBuilder<C> {
134        AuthorizerBuilder {
135            key_source_type: KeySourceType::ED(path.to_owned()),
136            refresh: Default::default(),
137            claims_checker: None,
138            validation: None,
139            jwt_source: JwtSource::AuthorizationHeader,
140            http_client: None,
141        }
142    }
143
144    /// Builds Authorizer Layer from a EC PEM raw text
145    pub fn from_ed_pem_text(text: &str) -> AuthorizerBuilder<C> {
146        AuthorizerBuilder {
147            key_source_type: KeySourceType::EDString(text.to_owned()),
148            refresh: Default::default(),
149            claims_checker: None,
150            validation: None,
151            jwt_source: JwtSource::AuthorizationHeader,
152            http_client: None,
153        }
154    }
155
156    /// Builds Authorizer Layer from a secret phrase
157    pub fn from_secret(secret: &str) -> AuthorizerBuilder<C> {
158        AuthorizerBuilder {
159            key_source_type: KeySourceType::Secret(secret.to_owned()),
160            refresh: Default::default(),
161            claims_checker: None,
162            validation: None,
163            jwt_source: JwtSource::AuthorizationHeader,
164            http_client: None,
165        }
166    }
167
168    /// Refreshes configuration for jwk store
169    pub fn refresh(mut self, refresh: Refresh) -> AuthorizerBuilder<C> {
170        if self.refresh.is_some() {
171            tracing::warn!("More than one refresh configuration found!");
172        }
173        self.refresh = Some(refresh);
174        self
175    }
176
177    /// no refresh, jwks will be loaded juste once
178    pub fn no_refresh(mut self) -> AuthorizerBuilder<C> {
179        if self.refresh.is_some() {
180            tracing::warn!("More than one refresh configuration found!");
181        }
182        self.refresh = Some(Refresh {
183            strategy: RefreshStrategy::NoRefresh,
184            ..Default::default()
185        });
186        self
187    }
188
189    /// configures token content check (custom function), if false a 403 will be sent.
190    /// (AuthError::InvalidClaims())
191    pub fn check<F>(mut self, checker_fn: F) -> AuthorizerBuilder<C>
192    where
193        F: Fn(&C) -> bool + Send + Sync + 'static,
194    {
195        self.claims_checker = Some(Arc::new(Box::new(checker_fn)));
196
197        self
198    }
199
200    pub fn validation(mut self, validation: Validation) -> AuthorizerBuilder<C> {
201        self.validation = Some(validation);
202
203        self
204    }
205
206    /// configures the source of the bearer token
207    ///
208    /// (default: AuthorizationHeader)
209    pub fn jwt_source(mut self, src: JwtSource) -> AuthorizerBuilder<C> {
210        self.jwt_source = src;
211
212        self
213    }
214
215    /// provide a custom http client for oicd requests
216    /// if not called, uses a default configured client
217    ///
218    /// (default: None)
219    pub fn http_client(mut self, http_client: Client) -> AuthorizerBuilder<C> {
220        self.http_client = Some(http_client);
221
222        self
223    }
224
225    /// Build layer
226    #[deprecated(since = "0.10.0", note = "please use `IntoLayer::into_layer()` instead")]
227    pub async fn layer(self) -> Result<AuthorizationLayer<C>, InitError> {
228        let val = self.validation.unwrap_or_default();
229        let auth = Arc::new(
230            Authorizer::build(
231                self.key_source_type,
232                self.claims_checker,
233                self.refresh,
234                val,
235                self.jwt_source,
236                None,
237            )
238            .await?,
239        );
240        Ok(AuthorizationLayer::new(vec![auth]))
241    }
242
243    pub async fn build(self) -> Result<Authorizer<C>, InitError> {
244        let val = self.validation.unwrap_or_default();
245
246        Authorizer::build(
247            self.key_source_type,
248            self.claims_checker,
249            self.refresh,
250            val,
251            self.jwt_source,
252            self.http_client,
253        )
254        .await
255    }
256}