minauthator/lib/kernel/src/context.rs
Matthieu Bessat 02e16a7e74 feat: support OIDC id_token
- generate JWT id_token in token exchange
- store optional nonce in authorization object
- switch to RS256 algorithm for JWT signature
- add JWKs endpoint to provide OIDC clients with public keys
2024-12-17 22:32:25 +01:00

91 lines
2.6 KiB
Rust

use std::{env, fs, path::Path};
use anyhow::{Result, Context, anyhow};
use fully_pub::fully_pub;
use log::info;
use crate::{
consts::{DEFAULT_CONFIG_PATH, DEFAULT_DB_PATH, DEFAULT_SIGNING_KEY_PATH},
database::prepare_database,
models::config::Config,
repositories::storage::Storage
};
/// get server config
fn get_config(path: String) -> Result<Config> {
let inp_def_yaml = fs::read_to_string(path)
.expect("Should have been able to read the the config file");
toml::from_str(&inp_def_yaml)
.map_err(|e| anyhow!("Failed to parse config, {:?}", e))
}
#[fully_pub]
struct StartKernelConfig {
config_path: Option<String>,
database_path: Option<String>,
}
#[derive(Debug, Clone)]
#[fully_pub]
struct AppSecrets {
/// RSA keypair (public, private) used to signed the JWT issued by minauthator in PEM conainer format
signing_keypair: (Vec<u8>, Vec<u8>)
}
#[derive(Debug, Clone)]
#[fully_pub]
struct ComputedConfig {
signing_public_key: Vec<u8>,
signing_private_key: Vec<u8>
}
#[derive(Debug, Clone)]
#[fully_pub]
struct KernelContext {
config: Config,
secrets: AppSecrets,
storage: Storage
}
fn get_signing_keypair(key_path: &str) -> Result<(Vec<u8>, Vec<u8>)> {
let key_path = Path::new(key_path);
let pub_key_path = key_path.with_extension("pub");
let private_key: Vec<u8> = fs::read_to_string(&key_path)
.context(format!("Failed to read private key from path {:?}.", key_path))?
.as_bytes().to_vec();
let public_key: Vec<u8> = fs::read_to_string(&pub_key_path)
.context(format!("Failed to read public key from path {:?}.", pub_key_path))?
.as_bytes().to_vec();
Ok((public_key, private_key))
}
pub async fn get_kernel_context(start_config: StartKernelConfig) -> Result<KernelContext> {
env_logger::init();
let _ = dotenvy::dotenv();
let database_path = &start_config.database_path.unwrap_or(DEFAULT_DB_PATH.to_string());
info!("Using database file at {}", database_path);
let storage = prepare_database(database_path).await.context("Could not prepare db.")?;
let config_path = start_config.config_path.unwrap_or(DEFAULT_CONFIG_PATH.to_string());
info!("Using config file at {}", &config_path);
let config: Config = get_config(config_path)
.expect("Cannot get config.");
let signing_key_path = config.signing_key.clone().unwrap_or(DEFAULT_SIGNING_KEY_PATH.to_string());
// optionally load dotenv file
let _ = dotenvy::dotenv();
let secrets = AppSecrets {
signing_keypair: get_signing_keypair(&signing_key_path)?
};
Ok(KernelContext {
config,
secrets,
storage
})
}