From 035e6b20c7edf0ffb9b5735254c0fc502a88e827 Mon Sep 17 00:00:00 2001 From: arrelin Date: Tue, 10 Mar 2026 14:45:08 +0300 Subject: [PATCH] mobile update --- backend/Cargo.toml | 4 +++- backend/src/main.rs | 7 +++++++ backend/src/routes/oauth.rs | 19 +++++++++++++++++-- frontend/src/pages/Login.tsx | 10 ++++++---- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 88d90c2..3c461f8 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -27,4 +27,6 @@ reqwest = { version = "0.13.1", features = ["json"] } rand = "0.9.2" uuid = { version = "1", features = ["v4"] } sha2 = "0.10" -hex = "0.4" \ No newline at end of file +hex = "0.4" +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } \ No newline at end of file diff --git a/backend/src/main.rs b/backend/src/main.rs index fa81f2b..8c5eabf 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -3,6 +3,13 @@ use sea_orm::DbErr; use sea_orm_migration::prelude::*; #[tokio::main] async fn main() -> Result<(), DbErr> { + tracing_subscriber::fmt() + .with_env_filter( + tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| "family_budget=debug,info".parse().unwrap()), + ) + .init(); + let db = establish_connection().await?; println!("Successfully connected to database!"); diff --git a/backend/src/routes/oauth.rs b/backend/src/routes/oauth.rs index b52ab4f..f36ea70 100644 --- a/backend/src/routes/oauth.rs +++ b/backend/src/routes/oauth.rs @@ -9,6 +9,7 @@ use sea_orm::{DatabaseConnection, EntityTrait}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use tower_sessions::Session; +use tracing::{info, warn}; use utoipa::ToSchema; use crate::auth::AuthBackend; @@ -116,6 +117,7 @@ pub async fn google_auth( let nonce = uuid::Uuid::new_v4().to_string(); let mobile_state = make_mobile_csrf_state(&nonce); let auth_url = oauth_service.get_auth_url_with_state(mobile_state); + info!("mobile google_auth: generated signed state for nonce={}", nonce); return Ok(Json(OAuthUrlResponse { url: auth_url })); } @@ -152,6 +154,7 @@ pub async fn google_callback( Query(query): Query, ) -> Result { let is_mobile = verify_mobile_csrf_state(&query.state); + info!("google_callback: state={} is_mobile={}", &query.state[..query.state.len().min(20)], is_mobile); if !is_mobile { let session_csrf: Option = session @@ -162,7 +165,10 @@ pub async fn google_callback( match session_csrf { Some(csrf) if csrf == query.state => {} - _ => return Err(StatusCode::UNAUTHORIZED), + _ => { + warn!("google_callback: CSRF mismatch, session_csrf={:?}", session_csrf.as_deref().map(|s| &s[..s.len().min(10)])); + return Err(StatusCode::UNAUTHORIZED); + } } } @@ -191,6 +197,7 @@ pub async fn google_callback( if is_mobile { let token = make_auth_token(user.id); + info!("google_callback: mobile auth for user_id={}, token_prefix={}", user.id, &token[..token.len().min(20)]); let deep_link = format!("com.arrelin.family-budget-android://auth?token={}", token); let html = format!( r#""#, @@ -231,7 +238,15 @@ pub async fn mobile_callback( State(db): State, Query(query): Query, ) -> Result, StatusCode> { - let user_id = verify_auth_token(&query.token).ok_or(StatusCode::UNAUTHORIZED)?; + info!("mobile_callback: received token_prefix={}", &query.token[..query.token.len().min(20)]); + let user_id = match verify_auth_token(&query.token) { + Some(id) => id, + None => { + warn!("mobile_callback: token verification failed for token={}", &query.token[..query.token.len().min(40)]); + return Err(StatusCode::UNAUTHORIZED); + } + }; + info!("mobile_callback: token valid for user_id={}", user_id); let user = User::find_by_id(user_id) .one(&db) diff --git a/frontend/src/pages/Login.tsx b/frontend/src/pages/Login.tsx index 9ebd797..0c4d992 100644 --- a/frontend/src/pages/Login.tsx +++ b/frontend/src/pages/Login.tsx @@ -30,18 +30,20 @@ export default function Login() { try { token = new URL(url).searchParams.get('token'); } catch { - setError(t('login.error')); + setError(t('login.authError')); return; } - if (!token) { setError(t('login.error')); return; } + if (!token) { setError(t('login.authError')); return; } try { setLoading(true); await authApi.mobileCallback(token); const me = await authApi.me(); setUser(me.data); - } catch { - setError(t('login.error')); + } catch (err: any) { + const status = err?.response?.status; + const msg = err?.response?.data ? JSON.stringify(err.response.data) : err?.message; + setError(`${status ?? 'network'}: ${msg}`); setLoading(false); } }); -- 2.49.1