Skip to content

Commit 2003d5c

Browse files
committed
Split delay computation into its own method and add test.
1 parent c0f2f79 commit 2003d5c

File tree

1 file changed

+21
-22
lines changed

1 file changed

+21
-22
lines changed

src/internet_identity/src/openid/generic.rs

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use super::{
44
};
55
use crate::openid::OpenIdCredential;
66
use crate::openid::OpenIdProvider;
7-
use crate::openid::MINUTE_NS;
87
use crate::secs_to_nanos;
98
use base64::prelude::BASE64_URL_SAFE_NO_PAD;
109
use base64::Engine;
@@ -38,13 +37,13 @@ const HTTP_STATUS_OK: u8 = 200;
3837

3938
// Fetch the certs every fifteen minutes, the responses are always
4039
// valid for a couple of hours so that should be enough margin.
41-
const FETCH_CERTS_INTERVAL: u64 = 60 * 15; // 15 minutes in seconds
40+
const FETCH_CERTS_INTERVAL_SECONDS: u64 = 60 * 15; // 15 minutes in seconds
4241

4342
// A JWT is only valid for a very small window, even if the JWT itself says it's valid for longer,
4443
// we only need it right after it's being issued to create a JWT delegation with its own expiry.
4544
// As the JWT is also used for registration, which may include longer user interaction,
4645
// we are using 10 minutes to account for potential clock offsets as well as users.
47-
const MAX_VALIDITY_WINDOW: u64 = 10 * MINUTE_NS; // Same as ingress expiry
46+
const MAX_VALIDITY_WINDOW_SECONDS: u64 = 10 * 60; // Same as ingress expiry
4847

4948
// Maximum length of the email claim in the JWT, in practice we expect the identity provider to
5049
// already validate it on their end for a sane maximum length. This is an additional sanity check.
@@ -180,9 +179,9 @@ fn compute_next_certs_fetch_delay<T, E>(
180179
result: &Result<T, E>,
181180
current_delay: Option<u64>,
182181
) -> Option<u64> {
183-
const MIN_DELAY: u64 = 60;
184-
const MAX_DELAY: u64 = FETCH_CERTS_INTERVAL;
185-
const MULTIPLIER: u64 = 2;
182+
const MIN_DELAY_SECONDS: u64 = 60;
183+
const MAX_DELAY_SECONDS: u64 = FETCH_CERTS_INTERVAL_SECONDS;
184+
const BACKOFF_MULTIPLIER: u64 = 2;
186185

187186
match result {
188187
// Reset delay to None so default (`FETCH_CERTS_INTERVAL`) delay is used.
@@ -193,8 +192,8 @@ fn compute_next_certs_fetch_delay<T, E>(
193192
// The delay should be at most `MAX_DELAY` and at minimum `MIN_DELAY`.
194193
Err(_) => Some(
195194
current_delay
196-
.map_or(MIN_DELAY, |d| d * MULTIPLIER)
197-
.clamp(MIN_DELAY, MAX_DELAY),
195+
.map_or(MIN_DELAY_SECONDS, |d| d * BACKOFF_MULTIPLIER)
196+
.clamp(MIN_DELAY_SECONDS, MAX_DELAY_SECONDS),
198197
),
199198
}
200199
}
@@ -210,7 +209,7 @@ fn schedule_fetch_certs(
210209
use std::time::Duration;
211210

212211
set_timer(
213-
Duration::from_secs(delay.unwrap_or(FETCH_CERTS_INTERVAL)),
212+
Duration::from_secs(delay.unwrap_or(FETCH_CERTS_INTERVAL_SECONDS)),
214213
move || {
215214
spawn(async move {
216215
let result = fetch_certs(jwks_uri.clone()).await;
@@ -378,7 +377,7 @@ fn verify_claims(
378377
if now > secs_to_nanos(claims.exp) {
379378
return Err(OpenIDJWTVerificationError::JWTExpired);
380379
}
381-
if now > secs_to_nanos(claims.iat) + MAX_VALIDITY_WINDOW {
380+
if now > secs_to_nanos(claims.iat + MAX_VALIDITY_WINDOW_SECONDS) {
382381
return Err(OpenIDJWTVerificationError::JWTExpired);
383382
}
384383
if now < secs_to_nanos(claims.iat) {
@@ -612,7 +611,7 @@ fn should_return_error_when_invalid_caller() {
612611

613612
#[test]
614613
fn should_return_error_when_no_longer_valid() {
615-
TEST_TIME.replace(time() + MAX_VALIDITY_WINDOW + 1);
614+
TEST_TIME.replace(time() + secs_to_nanos(MAX_VALIDITY_WINDOW_SECONDS) + 1);
616615
let (_, salt, config, claims) = test_data();
617616

618617
assert_eq!(
@@ -663,28 +662,28 @@ fn should_return_error_when_name_too_long() {
663662
}
664663
#[test]
665664
fn should_compute_next_certs_fetch_delay() {
666-
const MIN_DELAY: u64 = 60;
667-
const MAX_DELAY: u64 = FETCH_CERTS_INTERVAL;
665+
const MIN_DELAY_SECONDS: u64 = 60;
666+
const MAX_DELAY_SECONDS: u64 = FETCH_CERTS_INTERVAL_SECONDS;
668667

669668
let success: Result<(), ()> = Ok(());
670669
let error: Result<(), ()> = Err(());
671670

672671
for (current_delay, expected_next_delay_on_error) in [
673672
// Should be at least `MIN_DELAY` (1 minute)
674-
(None, Some(MIN_DELAY)),
675-
(Some(0), Some(MIN_DELAY)),
676-
(Some(1), Some(MIN_DELAY)),
677-
(Some(MIN_DELAY / 2 - 1), Some(MIN_DELAY)),
673+
(None, Some(MIN_DELAY_SECONDS)),
674+
(Some(0), Some(MIN_DELAY_SECONDS)),
675+
(Some(1), Some(MIN_DELAY_SECONDS)),
676+
(Some(MIN_DELAY_SECONDS / 2 - 1), Some(MIN_DELAY_SECONDS)),
678677
// Should be multiplied by two
679-
(Some(MIN_DELAY / 2), Some(MIN_DELAY)),
680-
(Some(MIN_DELAY / 2 + 1), Some(MIN_DELAY + 2)),
678+
(Some(MIN_DELAY_SECONDS / 2), Some(MIN_DELAY_SECONDS)),
679+
(Some(MIN_DELAY_SECONDS / 2 + 1), Some(MIN_DELAY_SECONDS + 2)),
681680
(Some(120), Some(240)),
682681
(Some(120), Some(240)),
683682
(Some(240), Some(480)),
684683
// Should be at most `MAX_DELAY` (15 minutes)
685-
(Some(480), Some(MAX_DELAY)),
686-
(Some(MAX_DELAY / 2 + 1), Some(MAX_DELAY)),
687-
(Some(MAX_DELAY * 2), Some(MAX_DELAY)),
684+
(Some(480), Some(MAX_DELAY_SECONDS)),
685+
(Some(MAX_DELAY_SECONDS / 2 + 1), Some(MAX_DELAY_SECONDS)),
686+
(Some(MAX_DELAY_SECONDS * 2), Some(MAX_DELAY_SECONDS)),
688687
] {
689688
// Should return `None` on success so default (`FETCH_CERTS_INTERVAL`) delay is used.
690689
assert_eq!(

0 commit comments

Comments
 (0)