Feat: JWT key generation

This commit is contained in:
Jett Chen 2024-11-22 11:49:50 +08:00
parent 321d36b743
commit d1a223fac9
6 changed files with 69 additions and 71 deletions

View file

@ -1,66 +0,0 @@
pub mod slack;
use self::grpc_defs::JwtInfo;
pub use super::{db, grpc_defs, settings::BurrowAuthServerConfig};
use anyhow::{anyhow, Result};
use jwt_simple::{
claims::{Claims, NoCustomClaims},
prelude::{Duration, Ed25519KeyPair, EdDSAKeyPairLike, EdDSAPublicKeyLike},
};
use serde::{Deserialize, Serialize};
pub type KeypairT = Ed25519KeyPair;
#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone)]
pub struct OpenIdUser {
pub sub: String,
pub name: String,
}
#[derive(Serialize, Deserialize, Debug)]
struct OpenIDCustomField {
pub name: String,
}
impl OpenIdUser {
pub fn try_from_jwt(jwt_info: &JwtInfo, keypair: &KeypairT) -> Result<Self> {
let claims = keypair
.public_key()
.verify_token::<OpenIDCustomField>(&jwt_info.jwt, None)?;
Ok(Self {
sub: claims.subject.ok_or(anyhow!("No Subject!"))?,
name: claims.custom.name,
})
}
}
impl JwtInfo {
fn try_from_oid(oid_user: OpenIdUser, keypair: &KeypairT) -> Result<Self> {
let claims = Claims::with_custom_claims(
OpenIDCustomField { name: oid_user.name },
Duration::from_days(10),
)
.with_subject(oid_user.sub);
let jwt = keypair.sign(claims)?;
Ok(Self { jwt })
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_jwt() -> Result<()> {
let key_pair = Ed25519KeyPair::generate();
let sample_usr = OpenIdUser {
sub: "Spanish".into(),
name: "Inquisition".into(),
};
let encoded = JwtInfo::try_from_oid(sample_usr.clone(), &key_pair)?;
println!("{}", encoded.jwt);
let decoded = OpenIdUser::try_from_jwt(&encoded, &key_pair)?;
assert_eq!(decoded, sample_usr);
Ok(())
}
}

View file

@ -1 +0,0 @@

View file

@ -1,6 +1,50 @@
pub mod client; pub mod client;
pub mod server; pub mod server;
use anyhow::Result;
use clap::{Args, Parser, Subcommand};
use server::providers::gen_keypem;
fn main() { #[derive(Parser)]
println!("Hello, world!"); #[command(name = "Burrow Server")]
#[command(author = "Hack Club <team@hackclub.com>")]
#[command(version = "0.1")]
#[command(
about = "Server for hosting auth logic of Burrow",
long_about = "Burrow is a 🚀 blazingly fast 🚀 tool designed to penetrate unnecessarily restrictive firewalls, providing teenagers worldwide with secure, less-filtered, and safe access to the internet!
It's being built by teenagers from Hack Club, in public! Check it out: https://github.com/hackclub/burrow
Spotted a bug? Please open an issue! https://github.com/hackclub/burrow/issues/new"
)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
StartServer,
#[command(name = "genkeys")]
GenKeys(GenKeyArgs),
}
#[derive(Args)]
pub struct GenKeyArgs {
#[arg(short, long, default_value = "false")]
pub raw: bool,
}
#[tokio::main]
async fn main() -> Result<()> {
let cli = Cli::parse();
match &cli.command {
Commands::GenKeys(args) => {
let pem = gen_keypem();
if args.raw {
println!(r"{pem:?}");
} else {
println!("Generated PEM:\n{pem}")
}
}
Commands::StartServer => todo!(),
};
Ok(())
} }

View file

@ -1,5 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use jwt_simple::prelude::Ed25519KeyPair;
use tonic::{Request, Response, Status}; use tonic::{Request, Response, Status};
use super::providers::{KeypairT, OpenIdUser}; use super::providers::{KeypairT, OpenIdUser};
@ -18,6 +19,17 @@ struct BurrowGrpcServer {
jwt_keypair: Arc<KeypairT>, jwt_keypair: Arc<KeypairT>,
} }
impl BurrowGrpcServer {
pub fn new() -> anyhow::Result<Self> {
let config = BurrowAuthServerConfig::new_dotenv()?;
let jwt_keypair = Ed25519KeyPair::from_pem(&config.jwt_pem)?;
Ok(Self {
config: Arc::new(config),
jwt_keypair: Arc::new(jwt_keypair),
})
}
}
#[tonic::async_trait] #[tonic::async_trait]
impl BurrowWeb for BurrowGrpcServer { impl BurrowWeb for BurrowGrpcServer {
async fn slack_auth( async fn slack_auth(

View file

@ -46,6 +46,16 @@ impl JwtInfo {
} }
} }
pub fn gen_keypem() -> String {
let keypair = KeypairT::generate();
keypair.to_pem()
}
pub fn parse_keypem(pem: &String) -> Result<KeypairT> {
let keypair = KeypairT::from_pem(&pem)?;
Ok(keypair)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View file

@ -3,8 +3,7 @@ use serde::Deserialize;
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct BurrowAuthServerConfig { pub struct BurrowAuthServerConfig {
jwt_secret_key: String, pub jwt_pem: String,
jwt_public_key: String,
} }
impl BurrowAuthServerConfig { impl BurrowAuthServerConfig {