summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock295
-rw-r--r--Cargo.toml4
-rw-r--r--crates/auth/Cargo.toml5
-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
10 files changed, 418 insertions, 14 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3dd458b..16b864f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -185,6 +185,12 @@ dependencies = [
]
[[package]]
+name = "atomic-waker"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
+
+[[package]]
name = "auth-service"
version = "0.1.0"
dependencies = [
@@ -199,12 +205,15 @@ dependencies = [
"nanoid",
"oauth2",
"reqwest",
+ "sellershut-core",
"serde",
"serde_json",
"sqlx",
"stack-up",
"time",
"tokio",
+ "tonic",
+ "tonic-reflection",
"tower",
"tower-http",
"tower-sessions",
@@ -764,6 +773,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
+name = "errno"
+version = "0.3.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
+dependencies = [
+ "libc",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
name = "etcetera"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -796,6 +815,18 @@ dependencies = [
]
[[package]]
+name = "fastrand"
+version = "2.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+
+[[package]]
+name = "fixedbitset"
+version = "0.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
+
+[[package]]
name = "flume"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1000,6 +1031,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
+name = "h2"
+version = "0.4.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785"
+dependencies = [
+ "atomic-waker",
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "http",
+ "indexmap",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
name = "hashbrown"
version = "0.15.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1163,6 +1213,7 @@ dependencies = [
"bytes",
"futures-channel",
"futures-util",
+ "h2",
"http",
"http-body",
"httparse",
@@ -1192,6 +1243,19 @@ dependencies = [
]
[[package]]
+name = "hyper-timeout"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
+dependencies = [
+ "hyper",
+ "hyper-util",
+ "pin-project-lite",
+ "tokio",
+ "tower-service",
+]
+
+[[package]]
name = "hyper-util"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1467,6 +1531,12 @@ dependencies = [
]
[[package]]
+name = "linux-raw-sys"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
+
+[[package]]
name = "litemap"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1588,6 +1658,12 @@ dependencies = [
]
[[package]]
+name = "multimap"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"
+
+[[package]]
name = "nanoid"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1821,6 +1897,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
+name = "petgraph"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
+name = "pin-project"
+version = "1.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
name = "pin-project-lite"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1909,6 +2015,80 @@ dependencies = [
]
[[package]]
+name = "prost"
+version = "0.13.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
+dependencies = [
+ "bytes",
+ "prost-derive",
+]
+
+[[package]]
+name = "prost-build"
+version = "0.13.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf"
+dependencies = [
+ "heck",
+ "itertools",
+ "log",
+ "multimap",
+ "once_cell",
+ "petgraph",
+ "prettyplease",
+ "prost",
+ "prost-types",
+ "pulldown-cmark",
+ "pulldown-cmark-to-cmark",
+ "regex",
+ "syn 2.0.104",
+ "tempfile",
+]
+
+[[package]]
+name = "prost-derive"
+version = "0.13.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
+dependencies = [
+ "anyhow",
+ "itertools",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.13.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16"
+dependencies = [
+ "prost",
+]
+
+[[package]]
+name = "pulldown-cmark"
+version = "0.12.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14"
+dependencies = [
+ "bitflags",
+ "memchr",
+ "unicase",
+]
+
+[[package]]
+name = "pulldown-cmark-to-cmark"
+version = "20.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c0f333311d2d8fda65bcf76af35054e9f38e253332a0289746156a59656988b"
+dependencies = [
+ "pulldown-cmark",
+]
+
+[[package]]
name = "quinn"
version = "0.11.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2224,6 +2404,19 @@ dependencies = [
]
[[package]]
+name = "rustix"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
name = "rustls"
version = "0.23.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2322,6 +2515,19 @@ dependencies = [
]
[[package]]
+name = "sellershut-core"
+version = "0.1.0"
+dependencies = [
+ "prost",
+ "serde",
+ "serde_json",
+ "time",
+ "tonic",
+ "tonic-build",
+ "tonic-types",
+]
+
+[[package]]
name = "semver"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2795,6 +3001,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
[[package]]
+name = "tempfile"
+version = "3.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
+dependencies = [
+ "fastrand",
+ "getrandom 0.3.3",
+ "once_cell",
+ "rustix",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2995,6 +3214,73 @@ dependencies = [
]
[[package]]
+name = "tonic"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9"
+dependencies = [
+ "async-trait",
+ "axum",
+ "base64",
+ "bytes",
+ "h2",
+ "http",
+ "http-body",
+ "http-body-util",
+ "hyper",
+ "hyper-timeout",
+ "hyper-util",
+ "percent-encoding",
+ "pin-project",
+ "prost",
+ "socket2",
+ "tokio",
+ "tokio-stream",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tonic-build"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eac6f67be712d12f0b41328db3137e0d0757645d8904b4cb7d51cd9c2279e847"
+dependencies = [
+ "prettyplease",
+ "proc-macro2",
+ "prost-build",
+ "prost-types",
+ "quote",
+ "syn 2.0.104",
+]
+
+[[package]]
+name = "tonic-reflection"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9687bd5bfeafebdded2356950f278bba8226f0b32109537c4253406e09aafe1"
+dependencies = [
+ "prost",
+ "prost-types",
+ "tokio",
+ "tokio-stream",
+ "tonic",
+]
+
+[[package]]
+name = "tonic-types"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07439468da24d5f211d3f3bd7b63665d8f45072804457e838a87414a478e2db8"
+dependencies = [
+ "prost",
+ "prost-types",
+ "tonic",
+]
+
+[[package]]
name = "tower"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3002,9 +3288,12 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
dependencies = [
"futures-core",
"futures-util",
+ "indexmap",
"pin-project-lite",
+ "slab",
"sync_wrapper",
"tokio",
+ "tokio-util",
"tower-layer",
"tower-service",
"tracing",
@@ -3209,6 +3498,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
+name = "unicase"
+version = "2.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
+
+[[package]]
name = "unicode-bidi"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 1283ad4..699ac91 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
[workspace]
-members = ["crates/*"]
+members = ["crates/*", "lib/*"]
resolver = "3"
[workspace.package]
@@ -18,12 +18,14 @@ config = { version = "0.15.13", default-features = false }
futures-util = { version = "0.3.31", default-features = false }
nanoid = "0.4.0"
reqwest = { version = "0.12.22", default-features = false }
+sellershut-core = { path = "lib/sellershut-core/" }
serde = "1.0.219"
serde_json = "1.0.140"
sqlx = "0.8.6"
stack-up = { git = "https://github.com/rtkay123/stack-up.git" }
time = { version = "0.3.41", default-features = false }
tokio = "1.46.1"
+tonic = "0.13.0"
tower = "0.5.2"
tower-http = "0.6.6"
tracing = "0.1.41"
diff --git a/crates/auth/Cargo.toml b/crates/auth/Cargo.toml
index 410c51e..cc6d676 100644
--- a/crates/auth/Cargo.toml
+++ b/crates/auth/Cargo.toml
@@ -19,12 +19,15 @@ jsonwebtoken = "9.3.1"
nanoid.workspace = true
oauth2 = "5.0.0"
reqwest = { workspace = true, features = ["json", "rustls-tls"] }
+sellershut-core = { workspace = true, features = ["auth", "serde"] }
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
sqlx = { workspace = true, features = ["macros", "migrate", "runtime-tokio", "time", "tls-rustls", "uuid"] }
time = { workspace = true, features = ["parsing", "serde"] }
tokio = { workspace = true, features = ["macros", "rt-multi-thread", "signal"] }
-tower = { workspace = true, features = ["util"] }
+tonic.workspace = true
+tonic-reflection = "0.13.0"
+tower = { workspace = true, features = ["steer", "util"] }
tower-http = { workspace = true, features = ["map-request-body", "trace", "util"] }
tower-sessions = "0.14.0"
tower-sessions-core = { version = "0.14.0", features = ["deletion-task"] }
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>,