Skip to content

Commit 76e045b

Browse files
feat: integrate authentication middleware with core AuthenticationClient
This commit integrates the authentication middleware implementation with the AuthenticationClient that was moved to the core keylime library, completing the authentication integration. Signed-off-by: Sergio Correia <[email protected]>
1 parent 5a5b89c commit 76e045b

File tree

1 file changed

+57
-27
lines changed

1 file changed

+57
-27
lines changed

keylime/src/resilient_client.rs

Lines changed: 57 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::auth::{AuthConfig, SessionToken};
1+
use crate::auth::{AuthConfig, AuthenticationClient, SessionToken};
22
use anyhow;
33
use async_trait::async_trait;
44
use http::Extensions;
@@ -93,17 +93,23 @@ struct TokenState {
9393
token: RwLock<Option<SessionToken>>,
9494
/// Mutex for refresh operations - ensures single writer
9595
refresh_lock: Mutex<()>,
96-
/// Authentication configuration
97-
auth_config: AuthConfig,
96+
/// Raw authentication client (no middleware to avoid loops)
97+
auth_client: AuthenticationClient,
9898
}
9999

100100
impl TokenState {
101-
fn new(auth_config: AuthConfig) -> Self {
102-
Self {
101+
fn new(
102+
auth_config: AuthConfig,
103+
) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
104+
// Create a raw authentication client to avoid middleware loops
105+
let auth_client = AuthenticationClient::new_raw(auth_config)
106+
.map_err(|e| format!("Failed to create auth client: {}", e))?;
107+
108+
Ok(Self {
103109
token: RwLock::new(None),
104110
refresh_lock: Mutex::new(()),
105-
auth_config,
106-
}
111+
auth_client,
112+
})
107113
}
108114

109115
async fn get_valid_token(
@@ -113,9 +119,9 @@ impl TokenState {
113119
{
114120
let token_guard = self.token.read().await;
115121
if let Some(ref token) = *token_guard {
116-
if token
117-
.is_valid(self.auth_config.token_refresh_buffer_minutes)
118-
{
122+
if token.is_valid(
123+
self.auth_client.config().token_refresh_buffer_minutes,
124+
) {
119125
debug!("Using existing valid token from middleware");
120126
return Ok(token.token.clone());
121127
}
@@ -136,19 +142,39 @@ impl TokenState {
136142
{
137143
let token_guard = self.token.read().await;
138144
if let Some(ref token) = *token_guard {
139-
if token
140-
.is_valid(self.auth_config.token_refresh_buffer_minutes)
141-
{
145+
if token.is_valid(
146+
self.auth_client.config().token_refresh_buffer_minutes,
147+
) {
142148
debug!("Token was refreshed by another request");
143149
return Ok(token.token.clone());
144150
}
145151
}
146152
}
147153

148-
// TODO: Next, we'll integrate with the actual AuthenticationClient
149-
// For now, this is a placeholder that will be replaced
150-
warn!("Token refresh not yet implemented");
151-
Err("Authentication not yet integrated".into())
154+
// Use the raw authentication client to get a new token with metadata
155+
debug!("Performing token refresh using raw authentication client");
156+
match self.auth_client.get_auth_token_with_metadata().await {
157+
Ok((token_string, expires_at, session_id)) => {
158+
let new_token = SessionToken {
159+
token: token_string.clone(),
160+
expires_at,
161+
session_id,
162+
};
163+
164+
// Store the new token
165+
{
166+
let mut token_guard = self.token.write().await;
167+
*token_guard = Some(new_token);
168+
}
169+
170+
debug!("Token refresh completed successfully");
171+
Ok(token_string)
172+
}
173+
Err(e) => {
174+
warn!("Token refresh failed: {}", e);
175+
Err(format!("Authentication failed: {}", e).into())
176+
}
177+
}
152178
}
153179

154180
async fn clear_token(&self) {
@@ -165,9 +191,11 @@ pub struct AuthenticationMiddleware {
165191
}
166192

167193
impl AuthenticationMiddleware {
168-
pub fn new(auth_config: AuthConfig) -> Self {
169-
let token_state = Arc::new(TokenState::new(auth_config));
170-
Self { token_state }
194+
pub fn new(
195+
auth_config: AuthConfig,
196+
) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
197+
let token_state = Arc::new(TokenState::new(auth_config)?);
198+
Ok(Self { token_state })
171199
}
172200

173201
fn is_auth_endpoint(&self, req: &reqwest::Request) -> bool {
@@ -279,7 +307,7 @@ impl ResilientClient {
279307
max_retries: u32,
280308
success_codes: &[StatusCode],
281309
max_delay: Option<std::time::Duration>,
282-
) -> Self {
310+
) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
283311
let base_client = client.unwrap_or_default();
284312
let final_max_delay = max_delay.unwrap_or(DEFAULT_MAX_DELAY);
285313

@@ -300,15 +328,15 @@ impl ResilientClient {
300328
// Add authentication middleware if config is provided
301329
if let Some(auth_cfg) = auth_config {
302330
debug!("Adding authentication middleware to client");
303-
let auth_middleware = AuthenticationMiddleware::new(auth_cfg);
331+
let auth_middleware = AuthenticationMiddleware::new(auth_cfg)?;
304332
builder = builder.with(auth_middleware);
305333
}
306334

307335
let client_with_middleware = builder.with(LoggingMiddleware).build();
308336

309-
Self {
337+
Ok(Self {
310338
client: client_with_middleware,
311-
}
339+
})
312340
}
313341

314342
/// Generates a six-character lowercase alphanumeric request ID.
@@ -715,7 +743,8 @@ mod tests {
715743
3,
716744
&[StatusCode::OK],
717745
None,
718-
);
746+
)
747+
.unwrap(); //#[allow_ci]
719748

720749
// Verify the client was created successfully
721750
}
@@ -730,7 +759,8 @@ mod tests {
730759
3,
731760
&[StatusCode::OK],
732761
None,
733-
);
762+
)
763+
.unwrap(); //#[allow_ci]
734764

735765
// Verify the client was created successfully
736766
}
@@ -748,7 +778,7 @@ mod tests {
748778
max_auth_retries: 3,
749779
};
750780

751-
let middleware = AuthenticationMiddleware::new(auth_config);
781+
let middleware = AuthenticationMiddleware::new(auth_config).unwrap(); //#[allow_ci]
752782

753783
// Mock a request to a sessions endpoint (should be detected as auth endpoint)
754784
let mock_request = reqwest::Request::new(

0 commit comments

Comments
 (0)