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}