backend/config/auth/jwks.rs
1//! Manages the [`JwkSet`] the server uses to validate tokens.
2
3use jsonwebtoken::jwk::{Jwk, JwkSet};
4use log::trace;
5use serde::Deserialize;
6
7/// In between struct for [`JwkSet`].
8///
9/// [`JwkSet`] doesn't work directly as `Keycloak` uses algorithms [`jsonwebtoken`] doesn't support. This mean deserialization would fail.
10#[derive(Debug, Clone, Deserialize)]
11struct JwkSetHelper {
12 /// The keys returned from the server.
13 ///
14 /// Keys that cannot be deserialized to [`Jwk`] will be ignored.
15 keys: Vec<serde_json::Value>,
16}
17
18/// Fetch jwks from the provided url and tries to parse them to [`JwkSet`].
19///
20/// # Panics
21/// * If the request to the auth server fails.
22/// * If the keys cannot be deserialized to [`JwkSetHelper`].
23#[allow(clippy::expect_used)]
24pub async fn fetch_keys(url: &str) -> JwkSet {
25 trace!("Fetching jwks from auth server...");
26 let keys = reqwest::get(url)
27 .await
28 .expect("Error fetching from auth server!")
29 .json::<JwkSetHelper>()
30 .await
31 .expect("Auth server returned invalid keys!")
32 .keys
33 .into_iter()
34 .filter_map(|key| serde_json::from_value::<Jwk>(key).ok())
35 .collect::<Vec<_>>();
36
37 JwkSet { keys }
38}