openidconnect/types/
jwks.rs1use crate::http_utils::{check_content_type, MIME_TYPE_JSON, MIME_TYPE_JWKS};
2use crate::types::jwk::{JsonWebKey, JsonWebKeyId, JwsSigningAlgorithm};
3use crate::{
4 AsyncHttpClient, DiscoveryError, HttpRequest, HttpResponse, JsonWebKeyUse, SyncHttpClient,
5};
6
7use http::header::ACCEPT;
8use http::{HeaderValue, Method, StatusCode};
9use serde::{Deserialize, Serialize};
10use serde_with::{serde_as, VecSkipError};
11
12use std::future::Future;
13
14new_url_type![
15 JsonWebKeySetUrl
17];
18
19#[serde_as]
21#[derive(Debug, Deserialize, PartialEq, Eq, Serialize)]
22pub struct JsonWebKeySet<K>
23where
24 K: JsonWebKey,
25{
26 #[serde(bound = "K: JsonWebKey")]
29 #[serde_as(as = "VecSkipError<_>")]
32 keys: Vec<K>,
33}
34
35pub(crate) fn check_key_compatibility<K>(
37 key: &K,
38 signing_algorithm: &K::SigningAlgorithm,
39) -> Result<(), &'static str>
40where
41 K: JsonWebKey,
42{
43 if let Some(use_) = key.key_use() {
45 if !use_.allows_signature() {
46 return Err("key usage not permitted for digital signatures");
47 }
48 }
49
50 if signing_algorithm.key_type().as_ref() != Some(key.key_type()) {
52 return Err("key type does not match signature algorithm");
53 }
54
55 match key.signing_alg() {
56 crate::JsonWebKeyAlgorithm::Unspecified => Ok(()),
58 crate::JsonWebKeyAlgorithm::Unsupported => Err("key algorithm is not a signing algorithm"),
59 crate::JsonWebKeyAlgorithm::Algorithm(key_alg) if key_alg == signing_algorithm => Ok(()),
60 crate::JsonWebKeyAlgorithm::Algorithm(_) => Err("incompatible key algorithm"),
61 }
62}
63
64impl<K> JsonWebKeySet<K>
65where
66 K: JsonWebKey,
67{
68 pub fn new(keys: Vec<K>) -> Self {
70 Self { keys }
71 }
72
73 pub(crate) fn filter_keys(
75 &self,
76 key_id: Option<&JsonWebKeyId>,
77 signature_alg: &K::SigningAlgorithm,
78 ) -> Vec<&K> {
79 self.keys()
80 .iter()
81 .filter(|key|
82 if key_id.is_some() && key_id != key.key_id() {
85 false
86 } else {
87 check_key_compatibility(*key, signature_alg).is_ok()
88 }
89 )
90 .collect()
91 }
92
93 pub fn fetch<C>(
97 url: &JsonWebKeySetUrl,
98 http_client: &C,
99 ) -> Result<Self, DiscoveryError<<C as SyncHttpClient>::Error>>
100 where
101 C: SyncHttpClient,
102 {
103 http_client
104 .call(Self::fetch_request(url).map_err(|err| {
105 DiscoveryError::Other(format!("failed to prepare request: {err}"))
106 })?)
107 .map_err(DiscoveryError::Request)
108 .and_then(Self::fetch_response)
109 }
110
111 pub fn fetch_async<'c, C>(
114 url: &JsonWebKeySetUrl,
115 http_client: &'c C,
116 ) -> impl Future<Output = Result<Self, DiscoveryError<<C as AsyncHttpClient<'c>>::Error>>> + 'c
117 where
118 Self: 'c,
119 C: AsyncHttpClient<'c>,
120 {
121 let fetch_request = Self::fetch_request(url)
122 .map_err(|err| DiscoveryError::Other(format!("failed to prepare request: {err}")));
123 Box::pin(async move {
124 http_client
125 .call(fetch_request?)
126 .await
127 .map_err(DiscoveryError::Request)
128 .and_then(Self::fetch_response)
129 })
130 }
131
132 fn fetch_request(url: &JsonWebKeySetUrl) -> Result<HttpRequest, http::Error> {
133 http::Request::builder()
134 .uri(url.to_string())
135 .method(Method::GET)
136 .header(ACCEPT, HeaderValue::from_static(MIME_TYPE_JSON))
137 .body(Vec::new())
138 }
139
140 fn fetch_response<RE>(http_response: HttpResponse) -> Result<Self, DiscoveryError<RE>>
141 where
142 RE: std::error::Error + 'static,
143 {
144 if http_response.status() != StatusCode::OK {
145 return Err(DiscoveryError::Response(
146 http_response.status(),
147 http_response.body().to_owned(),
148 format!("HTTP status code {}", http_response.status()),
149 ));
150 }
151
152 check_content_type(http_response.headers(), MIME_TYPE_JSON)
153 .or_else(|err| {
154 check_content_type(http_response.headers(), MIME_TYPE_JWKS).map_err(|_| err)
155 })
156 .map_err(|err_msg| {
157 DiscoveryError::Response(
158 http_response.status(),
159 http_response.body().to_owned(),
160 err_msg,
161 )
162 })?;
163
164 serde_path_to_error::deserialize(&mut serde_json::Deserializer::from_slice(
165 http_response.body(),
166 ))
167 .map_err(DiscoveryError::Parse)
168 }
169
170 pub fn keys(&self) -> &Vec<K> {
172 &self.keys
173 }
174}
175impl<K> Clone for JsonWebKeySet<K>
176where
177 K: JsonWebKey,
178{
179 fn clone(&self) -> Self {
180 Self::new(self.keys.clone())
181 }
182}
183impl<K> Default for JsonWebKeySet<K>
184where
185 K: JsonWebKey,
186{
187 fn default() -> Self {
188 Self::new(Vec::new())
189 }
190}