summaryrefslogtreecommitdiffstats
path: root/crates/auth/src
diff options
context:
space:
mode:
authorrtkay123 <dev@kanjala.com>2025-07-25 18:37:32 +0200
committerrtkay123 <dev@kanjala.com>2025-07-25 18:37:32 +0200
commit3406efe921e877878d8ba656651e0d90382586ae (patch)
tree72538576df711385490d12a4ef9fed0781ce9de2 /crates/auth/src
parent3831e5a42ab4e21f116537c5251582245de37f0b (diff)
downloadsellershut-3406efe921e877878d8ba656651e0d90382586ae.tar.bz2
sellershut-3406efe921e877878d8ba656651e0d90382586ae.zip
feat(auth): validate token
Diffstat (limited to 'crates/auth/src')
-rw-r--r--crates/auth/src/auth.rs12
-rw-r--r--crates/auth/src/main.rs41
-rw-r--r--crates/auth/src/server.rs1
-rw-r--r--crates/auth/src/server/grpc.rs2
-rw-r--r--crates/auth/src/server/grpc/auth.rs50
-rw-r--r--crates/auth/src/server/grpc/interceptor.rs11
-rw-r--r--crates/auth/src/server/routes/authorised.rs11
7 files changed, 116 insertions, 12 deletions
diff --git a/crates/auth/src/auth.rs b/crates/auth/src/auth.rs
new file mode 100644
index 0000000..04cb60a
--- /dev/null
+++ b/crates/auth/src/auth.rs
@@ -0,0 +1,12 @@
+use serde::{Deserialize, Serialize};
+use uuid::Uuid;
+
+#[derive(Debug, Serialize, Deserialize)]
+pub struct Claims {
+ pub iss: String,
+ pub sub: Uuid,
+ pub exp: i64,
+ pub iat: i64,
+ pub sid: String,
+ pub aud: String,
+}
diff --git a/crates/auth/src/main.rs b/crates/auth/src/main.rs
index a1883ad..72f991f 100644
--- a/crates/auth/src/main.rs
+++ b/crates/auth/src/main.rs
@@ -1,3 +1,4 @@
+mod auth;
mod client;
mod cnfg;
mod error;
@@ -7,11 +8,19 @@ mod state;
use std::net::{Ipv6Addr, SocketAddr};
use clap::Parser;
+use reqwest::header::CONTENT_TYPE;
+use sellershut_core::auth::{AUTH_FILE_DESCRIPTOR_SET, auth_server::AuthServer};
use stack_up::{Configuration, Services, tracing::Tracing};
use tokio::{signal, task::AbortHandle};
+use tonic::service::Routes;
+use tower::{make::Shared, steer::Steer};
use tracing::{info, trace};
-use crate::{error::AppError, state::AppState};
+use crate::{
+ error::AppError,
+ server::{grpc::interceptor::MyInterceptor, routes::authorised::AuthRequest},
+ state::AppState,
+};
/// auth-service
#[derive(Parser, Debug)]
@@ -63,7 +72,35 @@ async fn main() -> Result<(), AppError> {
let listener = tokio::net::TcpListener::bind(addr).await?;
info!(port = addr.port(), "serving api");
- axum::serve(listener, server::router(state))
+ let service = AuthServer::with_interceptor(state.clone(), MyInterceptor);
+ let auth_reflector = tonic_reflection::server::Builder::configure()
+ .register_encoded_file_descriptor_set(AUTH_FILE_DESCRIPTOR_SET)
+ .build_v1()?;
+
+ let grpc_server = Routes::new(service)
+ .add_service(auth_reflector)
+ .into_axum_router();
+
+ let service = Steer::new(
+ vec![server::router(state), grpc_server],
+ |req: &axum::extract::Request, _services: &[_]| {
+ if req
+ .headers()
+ .get(CONTENT_TYPE)
+ .map(|content_type| content_type.as_bytes())
+ .filter(|content_type| content_type.starts_with(b"application/grpc"))
+ .is_some()
+ {
+ // grpc service
+ 1
+ } else {
+ // http service
+ 0
+ }
+ },
+ );
+
+ axum::serve(listener, Shared::new(service))
.with_graceful_shutdown(shutdown_signal(deletion_task.abort_handle()))
.await?;
diff --git a/crates/auth/src/server.rs b/crates/auth/src/server.rs
index 2892412..7b66c42 100644
--- a/crates/auth/src/server.rs
+++ b/crates/auth/src/server.rs
@@ -7,6 +7,7 @@ use crate::{
};
pub mod csrf_token_validation;
+pub mod grpc;
pub mod routes;
const CSRF_TOKEN: &str = "csrf_token";
diff --git a/crates/auth/src/server/grpc.rs b/crates/auth/src/server/grpc.rs
new file mode 100644
index 0000000..0fd775b
--- /dev/null
+++ b/crates/auth/src/server/grpc.rs
@@ -0,0 +1,2 @@
+pub mod auth;
+pub mod interceptor;
diff --git a/crates/auth/src/server/grpc/auth.rs b/crates/auth/src/server/grpc/auth.rs
new file mode 100644
index 0000000..fb00291
--- /dev/null
+++ b/crates/auth/src/server/grpc/auth.rs
@@ -0,0 +1,50 @@
+use std::str::FromStr;
+
+use jsonwebtoken::DecodingKey;
+use sellershut_core::auth::{ValidationRequest, ValidationResponse, auth_server::Auth};
+use tonic::{Request, Response, Status, async_trait};
+use tower_sessions::{SessionStore, session::Id};
+use tracing::warn;
+
+use crate::{auth::Claims, state::AppHandle};
+
+#[async_trait]
+impl Auth for AppHandle {
+ async fn validate_auth_token(
+ &self,
+ request: Request<ValidationRequest>,
+ ) -> Result<Response<ValidationResponse>, Status> {
+ let token = request.into_inner().token;
+
+ let token = jsonwebtoken::decode::<Claims>(
+ &token,
+ &DecodingKey::from_secret(self.local_config.oauth.jwt_encoding_key.as_bytes()),
+ &jsonwebtoken::Validation::default(),
+ );
+
+ match token {
+ Ok(value) => {
+ let session_id = value.claims.sid;
+ let store = &self.session_store;
+ match Id::from_str(&session_id) {
+ Ok(ref id) => {
+ if let Ok(Some(_)) = store.load(id).await {
+ return Ok(Response::new(ValidationResponse { valid: true }));
+ } else {
+ return Ok(Response::new(Default::default()));
+ }
+ }
+ Err(e) => {
+ warn!("{e}");
+
+ return Ok(Response::new(Default::default()));
+ }
+ }
+ }
+ Err(e) => {
+ warn!("{e}");
+ Ok(Response::new(ValidationResponse::default()))
+ }
+ }
+ }
+}
diff --git a/crates/auth/src/server/grpc/interceptor.rs b/crates/auth/src/server/grpc/interceptor.rs
new file mode 100644
index 0000000..6fbe7fa
--- /dev/null
+++ b/crates/auth/src/server/grpc/interceptor.rs
@@ -0,0 +1,11 @@
+use tonic::{Status, service::Interceptor};
+use tracing::Span;
+
+#[derive(Clone, Copy)]
+pub struct MyInterceptor;
+
+impl Interceptor for MyInterceptor {
+ fn call(&mut self, request: tonic::Request<()>) -> Result<tonic::Request<()>, Status> {
+ Ok(request)
+ }
+}
diff --git a/crates/auth/src/server/routes/authorised.rs b/crates/auth/src/server/routes/authorised.rs
index 27f02bc..50fcfc8 100644
--- a/crates/auth/src/server/routes/authorised.rs
+++ b/crates/auth/src/server/routes/authorised.rs
@@ -19,6 +19,7 @@ use tower_sessions::{
use uuid::Uuid;
use crate::{
+ auth::Claims,
error::AppError,
server::{
OAUTH_CSRF_COOKIE, csrf_token_validation::csrf_token_validation_workflow, routes::Provider,
@@ -55,16 +56,6 @@ struct DbUser {
const SESSION_COOKIE: &str = "info";
const SESSION_DATA_KEY: &str = "data";
-#[derive(Debug, Serialize, Deserialize)]
-struct Claims {
- iss: String,
- sub: Uuid,
- exp: i64,
- iat: i64,
- sid: String,
- aud: String,
-}
-
pub async fn login_authorised(
Query(query): Query<AuthRequest>,
State(state): State<AppHandle>,