Skip to content

Commit 400bf41

Browse files
committed
fix: populate token_received_at to enable proactive token refresh
Since build_token_response already recalculates expires_in as remaining time from stored expires_at, setting token_received_at=now at load time makes rmcp's expiry math correct (remaining = expires_in - 0), enabling client-side token refresh before expiry instead of waiting for a 401. Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
1 parent 6f912eb commit 400bf41

1 file changed

Lines changed: 17 additions & 3 deletions

File tree

crates/mcpmux-gateway/src/pool/credential_store.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//! CredentialStore interface.
66
77
use std::sync::Arc;
8+
use std::time::{SystemTime, UNIX_EPOCH};
89

910
use async_trait::async_trait;
1011
use chrono::{Duration, Utc};
@@ -159,6 +160,19 @@ impl DatabaseCredentialStore {
159160
}
160161
}
161162

163+
/// Current time as seconds since UNIX epoch, matching rmcp's `AuthorizationManager::now_epoch_secs()`.
164+
///
165+
/// Used when loading credentials from the database: since `build_token_response` recalculates
166+
/// `expires_in` as remaining time from the stored `expires_at`, setting `token_received_at = now`
167+
/// makes rmcp's expiry arithmetic correct (`remaining = expires_in - (now - received_at)` = `expires_in`),
168+
/// enabling proactive token refresh before expiry instead of waiting for a 401.
169+
fn now_epoch_secs() -> u64 {
170+
SystemTime::now()
171+
.duration_since(UNIX_EPOCH)
172+
.unwrap_or_default()
173+
.as_secs()
174+
}
175+
162176
#[async_trait]
163177
impl CredentialStore for DatabaseCredentialStore {
164178
async fn load(&self) -> Result<Option<StoredCredentials>, AuthError> {
@@ -208,7 +222,7 @@ impl CredentialStore for DatabaseCredentialStore {
208222
client_id: reg.client_id,
209223
token_response: Some(token_response),
210224
granted_scopes: Vec::new(),
211-
token_received_at: None,
225+
token_received_at: Some(now_epoch_secs()),
212226
})
213227
}
214228
(Some(reg), None) => {
@@ -220,7 +234,7 @@ impl CredentialStore for DatabaseCredentialStore {
220234
client_id: reg.client_id,
221235
token_response: None,
222236
granted_scopes: Vec::new(),
223-
token_received_at: None,
237+
token_received_at: Some(now_epoch_secs()),
224238
})
225239
}
226240
(None, Some(access)) => {
@@ -233,7 +247,7 @@ impl CredentialStore for DatabaseCredentialStore {
233247
client_id: String::new(),
234248
token_response: Some(token_response),
235249
granted_scopes: Vec::new(),
236-
token_received_at: None,
250+
token_received_at: Some(now_epoch_secs()),
237251
})
238252
}
239253
(None, None) => {

0 commit comments

Comments
 (0)