openid_client/issuer/
jwks.rs

1//! Issuer methods for Keystore
2
3use std::{
4    collections::{hash_map::DefaultHasher, HashMap},
5    hash::{Hash, Hasher},
6};
7
8use serde_json::Value;
9
10use crate::{
11    issuer::Issuer,
12    jwks::Jwks,
13    types::{query_keystore::QueryKeyStore, OidcClientError, OidcHttpClient, OidcReturnType},
14};
15
16/// [Issuer]'s Keystore methods
17impl Issuer {
18    pub(crate) async fn query_keystore_async<T>(
19        &mut self,
20        mut query: QueryKeyStore,
21        allow_multi: bool,
22        http_client: &T,
23    ) -> OidcReturnType<Jwks>
24    where
25        T: OidcHttpClient,
26    {
27        let mut hasher = DefaultHasher::new();
28        query.hash(&mut hasher);
29        let hash = hasher.finish();
30
31        match &mut self.keystore {
32            Some(keystore) => {
33                let reload = keystore.cache.contains_key(&hash)
34                    || (self.now)() - keystore.last_accessed > 60;
35
36                let jwks = keystore.get_keystore_async(reload, http_client).await?;
37
38                let keys = jwks.get(
39                    query.alg.clone(),
40                    query.key_use.clone(),
41                    query.key_id.clone(),
42                )?;
43
44                let alg = query.alg.clone();
45
46                // Why delete and print in the error below?
47                query.alg = None;
48
49                if keys.is_empty() {
50                    let message = format!("no valid key found in issuer\'s jwks_uri for key parameters kid: {}, alg: {}, key_use: {}", query.key_id.unwrap_or("".to_string()), alg.unwrap_or("".to_string()), query.key_use.unwrap_or("".to_string()));
51
52                    return Err(Box::new(OidcClientError::new_rp_error(&message, None)));
53                }
54
55                if !allow_multi && keys.len() > 1 && query.key_id.is_none() {
56                    let message = format!("multiple matching keys found in issuer\'s jwks_uri for key parameters kid: {}, key_use: {}, alg: {}, kid must be provided in this case", query.key_id.unwrap_or("".to_string()), query.key_use.unwrap_or("".to_string()), alg.unwrap_or("".to_string()));
57
58                    let mut extra_data = HashMap::<String, Value>::new();
59
60                    let json_jwks = match serde_json::to_value(&jwks) {
61                        Ok(v) => v,
62                        Err(_) => {
63                            return Err(Box::new(OidcClientError::new_error(
64                                "Malformed jwks",
65                                None,
66                            )))
67                        }
68                    };
69
70                    extra_data.insert("jwks".to_string(), json_jwks);
71
72                    return Err(Box::new(OidcClientError::new_rp_error(&message, None)));
73                }
74
75                keystore.cache.insert(hash, true);
76
77                Ok(jwks)
78            }
79            _ => Err(Box::new(OidcClientError::new_error(
80                "No Keystore found for this issuer",
81                None,
82            ))),
83        }
84    }
85
86    /// Reload Issuer Jwks
87    /// This method force refreshes the issuer Jwks using the configured Jwks Uri.
88    /// If no `jwks_uri` is found, returns an [OidcClientError].
89    pub async fn reload_jwks_async<T>(&mut self, http_client: &T) -> OidcReturnType<bool>
90    where
91        T: OidcHttpClient,
92    {
93        match &mut self.keystore {
94            Some(keystore) => {
95                keystore.get_keystore_async(true, http_client).await?;
96                Ok(true)
97            }
98            _ => Err(Box::new(OidcClientError::new_error(
99                "No Keystore found for this issuer",
100                None,
101            ))),
102        }
103    }
104}