tower_oauth2_resource_server/
builder.rs1use std::{marker::PhantomData, sync::Arc};
2
3use serde::de::DeserializeOwned;
4
5use crate::{
6 auth_resolver::{AuthorizerResolver, IssuerAuthorizerResolver, SingleAuthorizerResolver},
7 error::StartupError,
8 jwt_resolver::BearerTokenResolver,
9 server::OAuth2ResourceServer,
10 tenant::TenantConfiguration,
11};
12
13pub struct OAuth2ResourceServerBuilder<Claims> {
14 tenant_configurations: Vec<TenantConfiguration>,
15 auth_resolver: Option<Arc<dyn AuthorizerResolver<Claims>>>,
16 bearer_token_resolver: Option<Arc<dyn BearerTokenResolver + Send + Sync>>,
17 phantom: PhantomData<Claims>,
18}
19
20impl<Claims> OAuth2ResourceServer<Claims>
21where
22 Claims: Clone + DeserializeOwned + Send + Sync + 'static,
23{
24 pub fn builder() -> OAuth2ResourceServerBuilder<Claims> {
25 OAuth2ResourceServerBuilder::new()
26 }
27}
28
29impl<Claims> OAuth2ResourceServerBuilder<Claims> {
30 fn new() -> Self {
31 OAuth2ResourceServerBuilder::<Claims> {
32 tenant_configurations: Vec::new(),
33 auth_resolver: None,
34 bearer_token_resolver: None,
35 phantom: PhantomData,
36 }
37 }
38}
39
40impl<Claims> OAuth2ResourceServerBuilder<Claims>
41where
42 Claims: Clone + DeserializeOwned + Send + Sync + 'static,
43{
44 pub fn add_tenant(mut self, tenant_configuration: TenantConfiguration) -> Self {
46 self.tenant_configurations.push(tenant_configuration);
47 self
48 }
49
50 pub fn add_tenants(mut self, tenant_configurations: Vec<TenantConfiguration>) -> Self {
52 self.tenant_configurations.extend(tenant_configurations);
53 self
54 }
55
56 pub fn auth_resolver(mut self, auth_resolver: Arc<dyn AuthorizerResolver<Claims>>) -> Self {
62 self.auth_resolver = Some(auth_resolver);
63 self
64 }
65
66 pub fn bearer_token_resolver(
72 mut self,
73 bearer_token_resolver: Arc<dyn BearerTokenResolver + Send + Sync>,
74 ) -> Self {
75 self.bearer_token_resolver = Some(bearer_token_resolver);
76 self
77 }
78
79 pub async fn build(self) -> Result<OAuth2ResourceServer<Claims>, StartupError> {
85 if self.tenant_configurations.is_empty() {
86 return Err(StartupError::InvalidParameter(
87 "At least one TenantConfiguration is required".to_owned(),
88 ));
89 }
90 let num_tenants = self.tenant_configurations.len();
91 let auth_resolver = self.auth_resolver.unwrap_or_else(|| {
92 if num_tenants == 1 {
93 Arc::new(SingleAuthorizerResolver {})
94 } else {
95 Arc::new(IssuerAuthorizerResolver {})
96 }
97 });
98 OAuth2ResourceServer::new(
99 self.tenant_configurations,
100 auth_resolver,
101 self.bearer_token_resolver,
102 )
103 .await
104 }
105}
106
107impl<Claims> Default for OAuth2ResourceServerBuilder<Claims> {
108 fn default() -> Self {
109 Self::new()
110 }
111}
112
113#[cfg(test)]
114mod tests {
115 use serde::Deserialize;
116
117 use super::*;
118
119 #[derive(Clone, Debug, Deserialize)]
120 struct Claims {}
121
122 #[tokio::test]
123 async fn should_require_tenant_configurations() {
124 let result = OAuth2ResourceServerBuilder::<Claims>::new().build().await;
125 assert!(result.is_err());
126 assert_eq!(
127 result.unwrap_err(),
128 StartupError::InvalidParameter(
129 "At least one TenantConfiguration is required".to_owned()
130 )
131 )
132 }
133}