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