ezidam + jwt: get key, import private key, create jwt claims and sign them

This commit is contained in:
Philippe Loctaux 2023-03-18 16:14:26 +01:00
parent ef8d75ecee
commit e99115e174
14 changed files with 217 additions and 5 deletions

58
crates/jwt/src/claims.rs Normal file
View file

@ -0,0 +1,58 @@
use crate::{Error, PrivateKey};
use chrono::Duration;
use jwt_compact::{Claims, Header, TimeOptions};
use serde::{Deserialize, Serialize};
use users::User;
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct JwtClaims {
// Standard JWT claims
#[serde(rename = "iss")]
pub issuer: String,
#[serde(rename = "sub")]
pub subject: String,
#[serde(rename = "aud")]
pub audience: String,
// Custom claims
pub username: String,
pub email: Option<String>,
pub is_admin: bool,
pub roles: Vec<String>,
}
impl JwtClaims {
pub fn new(
issuer: impl Into<String>,
audience: impl Into<String>,
user: &User,
roles: Vec<String>,
) -> Self {
Self {
// Standard JWT claims
issuer: issuer.into(),
subject: user.id().to_string(),
audience: audience.into(),
// Custom claims
username: user.username().to_string(),
email: user.email().map(String::from),
is_admin: user.is_admin(),
roles,
}
}
pub fn sign_serialize(self, key: &PrivateKey) -> Result<String, Error> {
let header = Header::default().with_key_id(key.id());
let claims = Claims::<Self>::new(self);
// Set duration
let duration = Duration::minutes(15);
let time_options = TimeOptions::default();
let claims = claims.set_duration_and_issuance(&time_options, duration);
key.sign_serialize_jwt(header, claims)
}
}

View file

@ -44,6 +44,10 @@ impl Key {
pub fn public_der(&self) -> &[u8] {
&self.public_der
}
pub fn is_revoked(&self) -> bool {
self.revoked_at.is_some()
}
}
impl From<DatabaseKeys> for Key {

View file

@ -20,4 +20,7 @@ pub enum Error {
#[error("Failed to serialize JWK: `{0}`")]
JwkSerialization(#[from] serde_json::Error),
#[error("Failed to create JWT: `{0}`")]
JwtCreation(#[from] jwt_compact::CreationError),
}

View file

@ -1,6 +1,7 @@
use crate::Error;
use crate::{Error, JwtClaims};
use id::KeyID;
use jwt_compact::alg::{RsaPrivateKey, StrongKey};
use jwt_compact::alg::{Rsa, RsaPrivateKey, StrongKey};
use jwt_compact::{AlgorithmExt, Claims, Header};
use rsa::pkcs8::der::zeroize::Zeroizing;
use rsa::pkcs8::{DecodePrivateKey, EncodePrivateKey};
@ -27,6 +28,18 @@ impl PrivateKey {
key: RsaPrivateKey::from_pkcs8_der(der)?,
})
}
pub fn id(&self) -> &str {
self.id.as_ref()
}
pub fn sign_serialize_jwt(
&self,
header: Header,
claims: Claims<JwtClaims>,
) -> Result<String, Error> {
Ok(Rsa::ps256().token(header, &claims, &self.key)?)
}
}
#[cfg(test)]

View file

@ -1,12 +1,14 @@
extern crate core;
mod claims;
pub mod database;
mod error;
mod jwk;
mod key;
mod token;
/// Exports
/// Export
pub use claims::JwtClaims;
pub use error::Error;
pub use key::generate;
pub use key::{PrivateKey, PublicKey};