chore(api): move token auth to rust api service

This commit is contained in:
alyssa 2024-08-04 07:29:57 +09:00
parent 8210cb23f6
commit cfde105e19
8 changed files with 83 additions and 27 deletions

28
Cargo.lock generated
View file

@ -1098,9 +1098,9 @@ checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.61" version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
dependencies = [ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
@ -2916,9 +2916,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.84" version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"wasm-bindgen-macro", "wasm-bindgen-macro",
@ -2926,24 +2926,24 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-backend" name = "wasm-bindgen-backend"
version = "0.2.84" version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"log", "log",
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.107", "syn 2.0.66",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.84" version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@ -2951,22 +2951,22 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.84" version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.107", "syn 2.0.66",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.84" version = "0.2.92"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
[[package]] [[package]]
name = "web-sys" name = "web-sys"

View file

@ -5,4 +5,5 @@ public class ApiConfig
public int Port { get; set; } = 5000; public int Port { get; set; } = 5000;
public string? ClientId { get; set; } public string? ClientId { get; set; }
public string? ClientSecret { get; set; } public string? ClientSecret { get; set; }
public bool TrustAuth { get; set; } = false;
} }

View file

@ -13,19 +13,13 @@ public class AuthorizationTokenHandlerMiddleware
_next = next; _next = next;
} }
public async Task Invoke(HttpContext ctx, IDatabase db) public async Task Invoke(HttpContext ctx, IDatabase db, ApiConfig cfg)
{ {
ctx.Request.Headers.TryGetValue("authorization", out var authHeaders); if (cfg.TrustAuth
if (authHeaders.Count > 0) && ctx.Request.Headers.TryGetValue("X-PluralKit-SystemId", out var sidHeaders)
{ && sidHeaders.Count > 0
var systemId = await db.Execute(conn => conn.QuerySingleOrDefaultAsync<SystemId?>( && int.TryParse(sidHeaders[0], out var systemId))
"select id from systems where token = @token", ctx.Items.Add("SystemId", new SystemId(systemId));
new { token = authHeaders[0] }
));
if (systemId != null)
ctx.Items.Add("SystemId", systemId);
}
await _next.Invoke(ctx); await _next.Invoke(ctx);
} }

View file

@ -0,0 +1,20 @@
pub async fn legacy_token_auth(
pool: &sqlx::postgres::PgPool,
token: &str,
) -> anyhow::Result<Option<i32>> {
let mut system: Vec<LegacyTokenDbResponse> =
sqlx::query_as("select id from systems where token = $1")
.bind(token)
.fetch_all(pool)
.await?;
Ok(if let Some(system) = system.pop() {
Some(system.id)
} else {
None
})
}
#[derive(sqlx::FromRow)]
struct LegacyTokenDbResponse {
id: i32,
}

View file

@ -1,2 +1,5 @@
mod stats; mod stats;
pub use stats::*; pub use stats::*;
mod auth;
pub use auth::*;

View file

@ -135,6 +135,7 @@ async fn main() -> anyhow::Result<()> {
.layer(axum::middleware::from_fn(middleware::logger)) .layer(axum::middleware::from_fn(middleware::logger))
.layer(middleware::ratelimit::ratelimiter(middleware::ratelimit::do_request_ratelimited)) // this sucks .layer(middleware::ratelimit::ratelimiter(middleware::ratelimit::do_request_ratelimited)) // this sucks
.layer(axum::middleware::from_fn_with_state(ctx.clone(), middleware::authnz))
.layer(axum::middleware::from_fn(middleware::ignore_invalid_routes)) .layer(axum::middleware::from_fn(middleware::ignore_invalid_routes))
.layer(axum::middleware::from_fn(middleware::cors)) .layer(axum::middleware::from_fn(middleware::cors))

View file

@ -0,0 +1,35 @@
use axum::{
extract::{Request, State},
http::HeaderValue,
middleware::Next,
response::Response,
};
use tracing::error;
use crate::ApiContext;
pub async fn authnz(State(ctx): State<ApiContext>, mut request: Request, next: Next) -> Response {
let headers = request.headers_mut();
headers.remove("x-pluralkit-systemid");
let auth_header = headers
.get("authorization")
.map(|h| h.to_str().ok())
.flatten();
if let Some(auth_header) = auth_header {
if let Some(system_id) =
match libpk::db::repository::legacy_token_auth(&ctx.db, auth_header).await {
Ok(val) => val,
Err(err) => {
error!(?err, "failed to query authorization token in postgres");
None
}
}
{
headers.append(
"x-pluralkit-systemid",
HeaderValue::from_str(format!("{system_id}").as_str()).unwrap(),
);
}
}
next.run(request).await
}

View file

@ -1,5 +1,4 @@
mod cors; mod cors;
pub use cors::cors; pub use cors::cors;
mod logger; mod logger;
@ -9,3 +8,6 @@ mod ignore_invalid_routes;
pub use ignore_invalid_routes::ignore_invalid_routes; pub use ignore_invalid_routes::ignore_invalid_routes;
pub mod ratelimit; pub mod ratelimit;
mod authnz;
pub use authnz::authnz;