max / makenotwork
1 file changed,
+10 insertions,
-0 deletions
| @@ -96,6 +96,11 @@ const SESSION_REFRESH_TOKEN: &str = "mnw_refresh_token"; | |||
| 96 | 96 | const SESSION_OAUTH_STATE: &str = "oauth_state"; | |
| 97 | 97 | const SESSION_PKCE_VERIFIER: &str = "pkce_verifier"; | |
| 98 | 98 | ||
| 99 | + | /// Per-request timeout for the outbound OAuth calls (userinfo, token refresh). | |
| 100 | + | /// Tighter than the shared client's 15s total and the outer 30s TimeoutLayer, so | |
| 101 | + | /// a stalled MNW OAuth endpoint fails the login/refresh fast instead of parking. | |
| 102 | + | const OAUTH_REQUEST_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10); | |
| 103 | + | ||
| 99 | 104 | impl SessionUser { | |
| 100 | 105 | async fn from_session(session: &Session) -> Option<Self> { | |
| 101 | 106 | let user_id: uuid::Uuid = match session.get(SESSION_USER_ID).await { | |
| @@ -282,6 +287,10 @@ async fn fetch_userinfo( | |||
| 282 | 287 | let res = http | |
| 283 | 288 | .get(&url) | |
| 284 | 289 | .bearer_auth(access_token) | |
| 290 | + | // Per-request timeout, tighter than the client's 15s total: an OAuth call | |
| 291 | + | // sits in the login/refresh path and should give up well before the outer | |
| 292 | + | // 30s request TimeoutLayer would (fuzz-2026-07-06 OAuth per-request timeout). | |
| 293 | + | .timeout(OAUTH_REQUEST_TIMEOUT) | |
| 285 | 294 | .send() | |
| 286 | 295 | .await | |
| 287 | 296 | .map_err(|e| { | |
| @@ -324,6 +333,7 @@ async fn exchange_refresh_token( | |||
| 324 | 333 | "refresh_token": refresh_token, | |
| 325 | 334 | "client_id": state.config.oauth_client_id, | |
| 326 | 335 | })) | |
| 336 | + | .timeout(OAUTH_REQUEST_TIMEOUT) | |
| 327 | 337 | .send() | |
| 328 | 338 | .await | |
| 329 | 339 | .map_err(|e| { |