From d230efb49ab9ed2de5f90445bea978a244c20aca Mon Sep 17 00:00:00 2001 From: Denis Varlakov Date: Tue, 5 Apr 2022 12:15:24 +0200 Subject: [PATCH] Finish AuthService --- Cargo.lock | 2 + delivery/trusted-delivery/server/Cargo.toml | 2 + .../trusted-delivery/server/src/auth/inner.rs | 12 ++- .../trusted-delivery/server/src/auth/mod.rs | 17 +++- delivery/trusted-delivery/server/src/lib.rs | 81 +++++++++++++++++++ 5 files changed, 107 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 48247dd..4f5b3dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3477,12 +3477,14 @@ dependencies = [ "chrono", "futures", "hex 0.4.3", + "http", "jsonwebtoken", "phantom-type", "rand 0.8.4", "serde", "thiserror", "tonic", + "tower-service", "trusted-delivery-api", "trusted-delivery-core", ] diff --git a/delivery/trusted-delivery/server/Cargo.toml b/delivery/trusted-delivery/server/Cargo.toml index 1175a57..d6fa6c6 100644 --- a/delivery/trusted-delivery/server/Cargo.toml +++ b/delivery/trusted-delivery/server/Cargo.toml @@ -14,6 +14,8 @@ trusted-delivery-core = { path = "../core" } tonic = "0.6" futures = "0.3" async-stream = "0.3" +tower-service = "0.3" +http = "0.2" # Crypto deps jsonwebtoken = "8" diff --git a/delivery/trusted-delivery/server/src/auth/inner.rs b/delivery/trusted-delivery/server/src/auth/inner.rs index 1431567..ac38daa 100644 --- a/delivery/trusted-delivery/server/src/auth/inner.rs +++ b/delivery/trusted-delivery/server/src/auth/inner.rs @@ -93,13 +93,13 @@ impl TokenVerifier { ) -> Result<(), InvalidToken> { let validation = jwt::Validation::new(JWT_ALGORITHM); let claims = jwt::decode::>(&token.0, &self.secret_key, &validation) - .map_err(InvalidToken::ValidateToken)? + .map_err(InvalidTokenReason::ValidateToken)? .claims; if *identity != claims.identity { - return Err(InvalidToken::MismatchedIdentity); + return Err(InvalidTokenReason::MismatchedIdentity.into()); } if *room_id != claims.room_id { - return Err(InvalidToken::MismatchedRoomId); + return Err(InvalidTokenReason::MismatchedRoomId.into()); } Ok(()) } @@ -128,7 +128,11 @@ pub enum AuthError { } #[derive(Debug, Error)] -pub enum InvalidToken { +#[error(transparent)] +pub struct InvalidToken(#[from] InvalidTokenReason); + +#[derive(Debug, Error)] +enum InvalidTokenReason { #[error(transparent)] ValidateToken(jwt::errors::Error), #[error("mismatched room id")] diff --git a/delivery/trusted-delivery/server/src/auth/mod.rs b/delivery/trusted-delivery/server/src/auth/mod.rs index c794bd4..628425e 100644 --- a/delivery/trusted-delivery/server/src/auth/mod.rs +++ b/delivery/trusted-delivery/server/src/auth/mod.rs @@ -13,10 +13,19 @@ use tonic::{Code, Request, Response, Status, Streaming}; use crate::auth::inner::AuthError; +pub use self::inner::{InvalidToken, TokenVerifier}; + mod inner; pub struct Auth(Arc>); +impl Auth { + pub fn new() -> (Self, TokenVerifier) { + let (inner, token_verifier) = inner::AuthInner::new(); + (Self(Arc::new(inner)), token_verifier) + } +} + #[tonic::async_trait] impl trusted_delivery_api::auth_server::Auth for Auth { type AuthStream = Pin> + Send>>; @@ -86,17 +95,19 @@ impl trusted_delivery_api::auth_server::Auth for Auth { token: String::from(token).into(), })), }; + yield msg4; + Ok(()) } Err(AuthError::InvalidSignature) => { - Err(Status::new(Code::Aborted, "invalid signature"))? + Err(Status::new(Code::Aborted, "invalid signature")) } Err(AuthError::GenerateToken(err)) => { Err(Status::new( Code::Internal, format!("generate jwt token: {}", err), - ))? + )) } - } + }? }))) } } diff --git a/delivery/trusted-delivery/server/src/lib.rs b/delivery/trusted-delivery/server/src/lib.rs index 42c0a87..5b6f8e6 100644 --- a/delivery/trusted-delivery/server/src/lib.rs +++ b/delivery/trusted-delivery/server/src/lib.rs @@ -1,6 +1,87 @@ +use std::task::{Context, Poll}; + use trusted_delivery_api::auth_server::AuthServer; use trusted_delivery_core::crypto::CryptoSuite; +pub use self::auth::{InvalidToken, TokenVerifier}; + mod auth; pub struct AuthService(AuthServer>); + +impl AuthService { + pub fn new() -> (Self, TokenVerifier) { + let (auth, token_verifier) = auth::Auth::new(); + (AuthService(AuthServer::new(auth)), token_verifier) + } +} + +macro_rules! derive_service_for_wrapper { + ($($service:ident as $underlying:ty),+) => { + use http::{Request, Response}; + use tonic::body::BoxBody; + use tonic::transport::Body; + use tonic::transport::NamedService; + use tower_service::Service; + + $( + impl Service> for $service { + type Response = Response; + type Error = <$underlying as tower_service::Service>>::Error; + type Future = <$underlying as tower_service::Service>>::Future; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + <$underlying as tower_service::Service>>::poll_ready( + &mut self.0, + cx, + ) + } + + fn call(&mut self, req: Request) -> Self::Future { + <$underlying as tower_service::Service>>::call(&mut self.0, req) + } + } + impl NamedService for $service { + const NAME: &'static str = <$underlying as tonic::transport::NamedService>::NAME; + } + impl Clone for $service { + fn clone(&self) -> Self { + Self(self.0.clone()) + } + } + )+ + }; +} + +derive_service_for_wrapper!(AuthService as AuthServer>); + +#[cfg(test)] +mod tests { + use std::error::Error; + + use http::{Request, Response}; + use tonic::body::BoxBody; + use tonic::transport::Body; + use tonic::transport::NamedService; + use tower_service::Service; + use trusted_delivery_core::crypto::CryptoSuite; + + fn _ensure_service_is_valid() + where + S: Service, Response = Response> + + NamedService + + Clone + + Send + + 'static, + S::Future: Send + 'static, + S::Error: Into> + Send, + { + } + + /// Compile-time check that services are compliant with [Server::add_service function] + /// + /// [Server::add_service function]: tonic::transport::Server::add_service + fn _ensure_services_are_valid() { + _ensure_service_is_valid::>(); + } +}