Improve API

This commit is contained in:
Pierre HUBERT 2024-04-20 13:36:41 +02:00
parent 9f56be95de
commit 4e8797d68d

View File

@ -35,37 +35,40 @@ pub fn generate_ec384_keypair() -> anyhow::Result<(TokenPubKey, TokenPrivKey)> {
TokenPrivKey::ES384 { r#priv: priv_pem }, TokenPrivKey::ES384 { r#priv: priv_pem },
)) ))
} }
impl TokenPrivKey {
/// Sign a JWT
pub fn sign_jwt<C: Serialize>(&self, claims: &C) -> anyhow::Result<String> {
match self {
TokenPrivKey::ES384 { r#priv } => {
let encoding_key = EncodingKey::from_ec_pem(r#priv.as_bytes())?;
/// Sign JWT with a private key Ok(jsonwebtoken::encode(
pub fn sign_jwt<C: Serialize>(key: &TokenPrivKey, claims: &C) -> anyhow::Result<String> { &jsonwebtoken::Header::new(Algorithm::ES384),
match key { &claims,
TokenPrivKey::ES384 { r#priv } => { &encoding_key,
let encoding_key = EncodingKey::from_ec_pem(r#priv.as_bytes())?; )?)
}
Ok(jsonwebtoken::encode(
&jsonwebtoken::Header::new(Algorithm::ES384),
&claims,
&encoding_key,
)?)
} }
} }
} }
/// Validate a given JWT impl TokenPubKey {
pub fn validate_jwt<E: DeserializeOwned>(key: &TokenPubKey, token: &str) -> anyhow::Result<E> { /// Validate a given JWT
match key { pub fn validate_jwt<E: DeserializeOwned>(&self, jwt: &str) -> anyhow::Result<E> {
TokenPubKey::ES384 { r#pub } => { match self {
let decoding_key = DecodingKey::from_ec_pem(r#pub.as_bytes())?; TokenPubKey::ES384 { r#pub } => {
let decoding_key = DecodingKey::from_ec_pem(r#pub.as_bytes())?;
let validation = Validation::new(Algorithm::ES384); let validation = Validation::new(Algorithm::ES384);
Ok(jsonwebtoken::decode::<E>(token, &decoding_key, &validation)?.claims) Ok(jsonwebtoken::decode::<E>(jwt, &decoding_key, &validation)?.claims)
}
} }
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::{generate_ec384_keypair, sign_jwt, validate_jwt}; use crate::generate_ec384_keypair;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -96,8 +99,10 @@ mod test {
fn jwt_encode_sign_verify_valid() { fn jwt_encode_sign_verify_valid() {
let (pub_key, priv_key) = generate_ec384_keypair().unwrap(); let (pub_key, priv_key) = generate_ec384_keypair().unwrap();
let claims = Claims::default(); let claims = Claims::default();
let jwt = sign_jwt(&priv_key, &claims).expect("Failed to sign JWT!"); let jwt = priv_key.sign_jwt(&claims).expect("Failed to sign JWT!");
let claims_out = validate_jwt::<Claims>(&pub_key, &jwt).expect("Failed to validate JWT!"); let claims_out = pub_key
.validate_jwt::<Claims>(&jwt)
.expect("Failed to validate JWT!");
assert_eq!(claims, claims_out) assert_eq!(claims, claims_out)
} }
@ -107,14 +112,17 @@ mod test {
let (_pub_key, priv_key) = generate_ec384_keypair().unwrap(); let (_pub_key, priv_key) = generate_ec384_keypair().unwrap();
let (pub_key_2, _priv_key_2) = generate_ec384_keypair().unwrap(); let (pub_key_2, _priv_key_2) = generate_ec384_keypair().unwrap();
let claims = Claims::default(); let claims = Claims::default();
let jwt = sign_jwt(&priv_key, &claims).expect("Failed to sign JWT!"); let jwt = priv_key.sign_jwt(&claims).expect("Failed to sign JWT!");
validate_jwt::<Claims>(&pub_key_2, &jwt).expect_err("JWT should not have validated!"); pub_key_2
.validate_jwt::<Claims>(&jwt)
.expect_err("JWT should not have validated!");
} }
#[test] #[test]
fn jwt_verify_random_string() { fn jwt_verify_random_string() {
let (pub_key, _priv_key) = generate_ec384_keypair().unwrap(); let (pub_key, _priv_key) = generate_ec384_keypair().unwrap();
validate_jwt::<Claims>(&pub_key, "random_string") pub_key
.validate_jwt::<Claims>("random_string")
.expect_err("JWT should not have validated!"); .expect_err("JWT should not have validated!");
} }
@ -125,16 +133,19 @@ mod test {
exp: time() - 100, exp: time() - 100,
..Default::default() ..Default::default()
}; };
let jwt = sign_jwt(&priv_key, &claims).expect("Failed to sign JWT!"); let jwt = priv_key.sign_jwt(&claims).expect("Failed to sign JWT!");
validate_jwt::<Claims>(&pub_key, &jwt).expect_err("JWT should not have validated!"); pub_key
.validate_jwt::<Claims>(&jwt)
.expect_err("JWT should not have validated!");
} }
#[test] #[test]
fn jwt_invalid_signature() { fn jwt_invalid_signature() {
let (pub_key, priv_key) = generate_ec384_keypair().unwrap(); let (pub_key, priv_key) = generate_ec384_keypair().unwrap();
let claims = Claims::default(); let claims = Claims::default();
let jwt = sign_jwt(&priv_key, &claims).expect("Failed to sign JWT!"); let jwt = priv_key.sign_jwt(&claims).expect("Failed to sign JWT!");
validate_jwt::<Claims>(&pub_key, &format!("{jwt}bad")) pub_key
.validate_jwt::<Claims>(&format!("{jwt}bad"))
.expect_err("JWT should not have validated!"); .expect_err("JWT should not have validated!");
} }
} }