1#[cfg(not(feature = "wasm"))]
2use std::time::Instant;
3#[cfg(feature = "wasm")]
4use web_time::Instant;
5use log::debug;
6use serde::{Deserialize, Serialize};
7use crate::{IDTokenCertNotFoundError, MyResult};
8
9#[derive(Serialize, Deserialize, Debug, Default)]
10pub struct Certs {
11 keys: Vec<Cert>,
12
13 #[serde(skip)]
17 cache_until: Option<Instant>,
18}
19
20#[derive(Serialize, Deserialize, Debug, Clone)]
21pub struct Cert {
22 pub kid: String,
23 pub e: String,
24 pub alg: String,
25 pub kty: String,
26 pub n: String,
27}
28
29impl Certs {
30 pub fn find_cert<T: AsRef<str>>(&self, alg: T, kid: T) -> MyResult<Cert> {
31 let alg = alg.as_ref();
32 let kid = kid.as_ref();
33
34 match self.keys.iter().find(|cert| cert.alg == alg && cert.kid == kid) {
35 Some(cert ) => Ok(cert.clone()),
36 None => Err(IDTokenCertNotFoundError::new(alg, kid))?,
37 }
38 }
39
40 #[inline]
41 pub fn set_cache_until<T>(&mut self, cache_until: T)
42 where T: Into<Option<Instant>>
43 {
44 let cache_until = cache_until.into();
45
46 debug!("set cache until to {:?}", cache_until);
47 self.cache_until = cache_until;
48 }
49
50 #[inline]
51 pub fn need_refresh(&self) -> bool {
52 self
53 .cache_until
54 .map(|until| until <= Instant::now())
55 .unwrap_or(true)
56 }
57}