diff options
Diffstat (limited to 'crates/auth-service/src')
-rw-r--r-- | crates/auth-service/src/server.rs | 1 | ||||
-rw-r--r-- | crates/auth-service/src/server/keys.rs | 38 | ||||
-rw-r--r-- | crates/auth-service/src/server/routes/authorised.rs | 12 |
3 files changed, 47 insertions, 4 deletions
diff --git a/crates/auth-service/src/server.rs b/crates/auth-service/src/server.rs index 7b66c42..3433cd2 100644 --- a/crates/auth-service/src/server.rs +++ b/crates/auth-service/src/server.rs @@ -7,6 +7,7 @@ use crate::{ }; pub mod csrf_token_validation; +pub mod keys; pub mod grpc; pub mod routes; diff --git a/crates/auth-service/src/server/keys.rs b/crates/auth-service/src/server/keys.rs new file mode 100644 index 0000000..5c9ee43 --- /dev/null +++ b/crates/auth-service/src/server/keys.rs @@ -0,0 +1,38 @@ +use rsa::{ + pkcs8::{EncodePrivateKey, EncodePublicKey, LineEnding}, + RsaPrivateKey, + RsaPublicKey, +}; + +use crate::error::AppError; + +/// A private/public key pair used for HTTP signatures +#[derive(Debug, Clone)] +pub struct Keypair { + /// Private key in PEM format + pub private_key: String, + /// Public key in PEM format + pub public_key: String, +} + +impl Keypair { + /// Helper method to turn this into an openssl private key + #[cfg(test)] + pub(crate) fn private_key(&self) -> Result<RsaPrivateKey, anyhow::Error> { + use rsa::pkcs8::DecodePrivateKey; + + Ok(RsaPrivateKey::from_pkcs8_pem(&self.private_key)?) + } +} + +pub fn generate_actor_keypair() -> Result<Keypair, AppError> { + let mut rng = rand::thread_rng(); + let rsa = RsaPrivateKey::new(&mut rng, 2048)?; + let pkey = RsaPublicKey::from(&rsa); + let public_key = pkey.to_public_key_pem(LineEnding::default())?; + let private_key = rsa.to_pkcs8_pem(LineEnding::default())?.to_string(); + Ok(Keypair { + private_key, + public_key, + }) +} diff --git a/crates/auth-service/src/server/routes/authorised.rs b/crates/auth-service/src/server/routes/authorised.rs index 2538cdc..b4c2e00 100644 --- a/crates/auth-service/src/server/routes/authorised.rs +++ b/crates/auth-service/src/server/routes/authorised.rs @@ -23,7 +23,7 @@ use crate::{ auth::Claims, error::AppError, server::{ - OAUTH_CSRF_COOKIE, csrf_token_validation::csrf_token_validation_workflow, routes::Provider, + csrf_token_validation::csrf_token_validation_workflow, keys::generate_actor_keypair, routes::Provider, OAUTH_CSRF_COOKIE }, state::AppHandle, }; @@ -49,6 +49,7 @@ struct User { struct DbUser { id: Uuid, email: String, + private_key: String, created_at: OffsetDateTime, updated_at: OffsetDateTime, } @@ -92,8 +93,6 @@ pub async fn login_authorised( .await .context("failed to deserialise response as JSON")?; - dbg!(&user_data); - let user_data: User = serde_json::from_value(user_data)?; if !user_data.verified { @@ -124,19 +123,22 @@ pub async fn login_authorised( .fetch_optional(&mut *transaction) .await?; + let keys = generate_actor_keypair()?; + let user = if let Some(user) = user { user } else { let uuid = uuid::Uuid::now_v7(); let user = sqlx::query_as!( DbUser, - "insert into auth_user (id, email) values ($1, $2) + "insert into auth_user (id, email, private_key) values ($1, $2, $3) on conflict (email) do update set email = excluded.email returning *; ", uuid, user_data.email, + keys.private_key, ) .fetch_one(&mut *transaction) .await?; @@ -180,6 +182,7 @@ pub async fn login_authorised( ), )?; + let user_request = CreateUserRequest { email: user_data.email.to_owned(), avatar: user_data.avatar.as_ref().map(|value| { @@ -188,6 +191,7 @@ pub async fn login_authorised( user_data.id ) }), + public_key: keys.public_key, }; store |