securitydept_token_set_context/access_token_substrate/
config.rs1use securitydept_oauth_provider::OidcSharedConfig;
2use securitydept_oauth_resource_server::OAuthResourceServerConfig;
3use serde::Deserialize;
4
5use super::capabilities::TokenPropagation;
6use crate::orchestration::BackendConfigError;
7
8pub trait AccessTokenSubstrateConfigSource {
21 fn resource_server_config(&self) -> &OAuthResourceServerConfig;
25
26 fn token_propagation(&self) -> &TokenPropagation;
28
29 fn resolve_resource_server(
37 &self,
38 shared: &OidcSharedConfig,
39 ) -> Result<OAuthResourceServerConfig, BackendConfigError> {
40 let mut rs = self.resource_server_config().clone();
41 rs.resolve_config(shared)?;
42 Ok(rs)
43 }
44
45 fn resolve_all(
52 &self,
53 shared: Option<&OidcSharedConfig>,
54 ) -> Result<ResolvedAccessTokenSubstrateConfig, BackendConfigError> {
55 let resource_server = if let Some(shared) = shared {
56 self.resolve_resource_server(shared)?
57 } else {
58 self.resource_server_config().clone()
59 };
60
61 Ok(ResolvedAccessTokenSubstrateConfig {
62 resource_server,
63 token_propagation: self.token_propagation().clone(),
64 })
65 }
66}
67
68#[derive(Debug, Clone, Deserialize, Default)]
82pub struct AccessTokenSubstrateConfig {
83 #[serde(default, flatten)]
85 pub resource_server: OAuthResourceServerConfig,
86
87 #[serde(default)]
89 pub token_propagation: TokenPropagation,
90}
91
92impl AccessTokenSubstrateConfigSource for AccessTokenSubstrateConfig {
93 fn resource_server_config(&self) -> &OAuthResourceServerConfig {
94 &self.resource_server
95 }
96
97 fn token_propagation(&self) -> &TokenPropagation {
98 &self.token_propagation
99 }
100}
101
102#[derive(Debug, Clone)]
112pub struct ResolvedAccessTokenSubstrateConfig {
113 pub resource_server: OAuthResourceServerConfig,
115 pub token_propagation: TokenPropagation,
117}
118
119#[cfg(test)]
120mod tests {
121 use securitydept_oauth_provider::{OAuthProviderRemoteConfig, OidcSharedConfig};
122 use securitydept_oauth_resource_server::OAuthResourceServerIntrospectionConfig;
123
124 use super::*;
125
126 #[test]
127 fn resolve_all_inherits_shared_defaults() {
128 let shared = OidcSharedConfig {
129 remote: OAuthProviderRemoteConfig {
130 well_known_url: Some(
131 "https://auth.example.com/.well-known/openid-configuration".to_string(),
132 ),
133 ..Default::default()
134 },
135 client_id: Some("shared-app".to_string()),
136 client_secret: Some("shared-secret".to_string()),
137 ..Default::default()
138 };
139
140 let raw = AccessTokenSubstrateConfig {
141 resource_server: OAuthResourceServerConfig {
142 introspection: Some(OAuthResourceServerIntrospectionConfig::default()),
143 ..Default::default()
144 },
145 ..Default::default()
146 };
147
148 let resolved = raw.resolve_all(Some(&shared)).expect("should resolve");
149 assert_eq!(
150 resolved
151 .resource_server
152 .introspection
153 .as_ref()
154 .unwrap()
155 .client_id
156 .as_deref(),
157 Some("shared-app"),
158 "introspection.client_id should inherit from [oidc]"
159 );
160 }
161
162 #[test]
163 fn resolve_all_without_shared_returns_raw() {
164 let raw = AccessTokenSubstrateConfig {
165 resource_server: OAuthResourceServerConfig::default(),
166 token_propagation: TokenPropagation::Disabled,
167 };
168
169 let resolved = raw
170 .resolve_all(None)
171 .expect("should resolve without shared");
172 assert!(
173 resolved.resource_server.remote.well_known_url.is_none(),
174 "no shared defaults should be applied"
175 );
176 assert!(matches!(
177 resolved.token_propagation,
178 TokenPropagation::Disabled
179 ));
180 }
181
182 #[test]
183 fn resolve_all_propagation_axis_passes_through() {
184 use crate::access_token_substrate::propagation::{
185 PropagationDestinationPolicy, TokenPropagatorConfig,
186 };
187
188 let raw = AccessTokenSubstrateConfig {
189 resource_server: OAuthResourceServerConfig::default(),
190 token_propagation: TokenPropagation::Enabled {
191 config: TokenPropagatorConfig {
192 destination_policy: PropagationDestinationPolicy {
193 allowed_targets: vec![],
194 ..Default::default()
195 },
196 ..Default::default()
197 },
198 },
199 };
200
201 let resolved = raw.resolve_all(None).expect("should resolve");
202 assert!(matches!(
203 resolved.token_propagation,
204 TokenPropagation::Enabled { .. }
205 ));
206 }
207}