diff --git a/src/internet_identity/src/openid/generic.rs b/src/internet_identity/src/openid/generic.rs index b372bb8f1c..3c9e3a5af1 100644 --- a/src/internet_identity/src/openid/generic.rs +++ b/src/internet_identity/src/openid/generic.rs @@ -167,7 +167,7 @@ impl Provider { let certs: Rc>> = Rc::new(RefCell::new(vec![])); #[cfg(not(test))] - schedule_fetch_certs(config.jwks_uri, Rc::clone(&certs), None); + schedule_fetch_certs(config.jwks_uri, Rc::clone(&certs), Some(0)); Provider { client_id: config.client_id, @@ -185,23 +185,29 @@ fn schedule_fetch_certs( ) { use ic_cdk::spawn; use ic_cdk_timers::set_timer; - use std::cmp::min; + use std::cmp::{max, min}; use std::time::Duration; - set_timer(Duration::from_secs(delay.unwrap_or(0)), move || { - spawn(async move { - let new_delay = match fetch_certs(jwks_uri.clone()).await { - Ok(certs) => { - certs_reference.replace(certs); - FETCH_CERTS_INTERVAL - } - // Try again earlier with backoff if fetch failed, the HTTP outcall responses - // aren't the same across nodes when we fetch at the moment of key rotation. - Err(_) => min(FETCH_CERTS_INTERVAL, delay.unwrap_or(60) * 2), - }; - schedule_fetch_certs(jwks_uri, certs_reference, Some(new_delay)); - }); - }); + set_timer( + Duration::from_secs(delay.unwrap_or(FETCH_CERTS_INTERVAL)), + move || { + spawn(async move { + let new_delay = match fetch_certs(jwks_uri.clone()).await { + Ok(certs) => { + certs_reference.replace(certs); + // Reset delay to None so default `FETCH_CERTS_INTERVAL` delay is used. + None + } + // Try again earlier with backoff if fetch failed, the HTTP outcall responses + // aren't the same across nodes when we fetch at the moment of key rotation. + // + // The delay should be at most `FETCH_CERTS_INTERVAL` and at minimum 60 * 2. + Err(_) => Some(min(FETCH_CERTS_INTERVAL, max(60, delay.unwrap_or(60)) * 2)), + }; + schedule_fetch_certs(jwks_uri, certs_reference, new_delay); + }); + }, + ); } #[cfg(not(test))] diff --git a/src/internet_identity/src/openid/google.rs b/src/internet_identity/src/openid/google.rs index ed2454d8bc..5f34f2dffe 100644 --- a/src/internet_identity/src/openid/google.rs +++ b/src/internet_identity/src/openid/google.rs @@ -158,7 +158,7 @@ impl Provider { let certs: Rc>> = Rc::new(RefCell::new(vec![])); #[cfg(not(test))] - schedule_fetch_certs(Rc::clone(&certs), None); + schedule_fetch_certs(Rc::clone(&certs), Some(0)); Provider { client_id: config.client_id, @@ -171,23 +171,29 @@ impl Provider { fn schedule_fetch_certs(certs_reference: Rc>>, delay: Option) { use ic_cdk::spawn; use ic_cdk_timers::set_timer; - use std::cmp::min; + use std::cmp::{max, min}; use std::time::Duration; - set_timer(Duration::from_secs(delay.unwrap_or(0)), move || { - spawn(async move { - let new_delay = match fetch_certs().await { - Ok(google_certs) => { - certs_reference.replace(google_certs); - FETCH_CERTS_INTERVAL - } - // Try again earlier with backoff if fetch failed, the HTTP outcall responses - // aren't the same across nodes when we fetch at the moment of key rotation. - Err(_) => min(FETCH_CERTS_INTERVAL, delay.unwrap_or(60) * 2), - }; - schedule_fetch_certs(certs_reference, Some(new_delay)); - }); - }); + set_timer( + Duration::from_secs(delay.unwrap_or(FETCH_CERTS_INTERVAL)), + move || { + spawn(async move { + let new_delay = match fetch_certs().await { + Ok(google_certs) => { + certs_reference.replace(google_certs); + // Reset delay to None so default `FETCH_CERTS_INTERVAL` delay is used. + None + } + // Try again earlier with backoff if fetch failed, the HTTP outcall responses + // aren't the same across nodes when we fetch at the moment of key rotation. + // + // The delay should be at most `FETCH_CERTS_INTERVAL` and at minimum 60 * 2. + Err(_) => Some(min(FETCH_CERTS_INTERVAL, max(60, delay.unwrap_or(60)) * 2)), + }; + schedule_fetch_certs(certs_reference, new_delay); + }); + }, + ); } #[cfg(not(test))]