Compare commits
4 Commits
bugfix/iro
...
7b7554c84b
| Author | SHA1 | Date | |
|---|---|---|---|
| 7b7554c84b | |||
| c884bf812c | |||
| 91f9ed5474 | |||
| adad656df2 |
@@ -28,5 +28,3 @@ rand = "0.9.2"
|
|||||||
uuid = { version = "1", features = ["v4"] }
|
uuid = { version = "1", features = ["v4"] }
|
||||||
sha2 = "0.10"
|
sha2 = "0.10"
|
||||||
hex = "0.4"
|
hex = "0.4"
|
||||||
tracing = "0.1"
|
|
||||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|
||||||
@@ -231,7 +231,7 @@ pub async fn create_app(db: DatabaseConnection) -> Result<Router, DbErr> {
|
|||||||
.url("/api-docs/openapi.json", ApiDoc::openapi());
|
.url("/api-docs/openapi.json", ApiDoc::openapi());
|
||||||
|
|
||||||
let allowed_origins = std::env::var("ALLOWED_ORIGINS")
|
let allowed_origins = std::env::var("ALLOWED_ORIGINS")
|
||||||
.unwrap_or_else(|_| "http://localhost:3000,http://localhost:5173,http://localhost:5174,http://localhost:5175,http://localhost:8080,http://localhost:1420,http://tauri.localhost,https://tauri.localhost".to_string());
|
.unwrap_or_else(|_| "http://localhost:3000,http://localhost:5173,http://localhost:5174,http://localhost:5175,http://localhost:8080".to_string());
|
||||||
|
|
||||||
let origins: Vec<HeaderValue> = allowed_origins
|
let origins: Vec<HeaderValue> = allowed_origins
|
||||||
.split(',')
|
.split(',')
|
||||||
|
|||||||
@@ -3,13 +3,6 @@ use sea_orm::DbErr;
|
|||||||
use sea_orm_migration::prelude::*;
|
use sea_orm_migration::prelude::*;
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), DbErr> {
|
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?;
|
let db = establish_connection().await?;
|
||||||
println!("Successfully connected to database!");
|
println!("Successfully connected to database!");
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ use sea_orm::{DatabaseConnection, EntityTrait};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use tower_sessions::Session;
|
use tower_sessions::Session;
|
||||||
use tracing::{info, warn};
|
|
||||||
use utoipa::ToSchema;
|
use utoipa::ToSchema;
|
||||||
|
|
||||||
use crate::auth::AuthBackend;
|
use crate::auth::AuthBackend;
|
||||||
@@ -117,7 +116,6 @@ pub async fn google_auth(
|
|||||||
let nonce = uuid::Uuid::new_v4().to_string();
|
let nonce = uuid::Uuid::new_v4().to_string();
|
||||||
let mobile_state = make_mobile_csrf_state(&nonce);
|
let mobile_state = make_mobile_csrf_state(&nonce);
|
||||||
let auth_url = oauth_service.get_auth_url_with_state(mobile_state);
|
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 }));
|
return Ok(Json(OAuthUrlResponse { url: auth_url }));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +152,6 @@ pub async fn google_callback(
|
|||||||
Query(query): Query<GoogleCallbackQuery>,
|
Query(query): Query<GoogleCallbackQuery>,
|
||||||
) -> Result<Response, StatusCode> {
|
) -> Result<Response, StatusCode> {
|
||||||
let is_mobile = verify_mobile_csrf_state(&query.state);
|
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 {
|
if !is_mobile {
|
||||||
let session_csrf: Option<String> = session
|
let session_csrf: Option<String> = session
|
||||||
@@ -165,10 +162,7 @@ pub async fn google_callback(
|
|||||||
|
|
||||||
match session_csrf {
|
match session_csrf {
|
||||||
Some(csrf) if csrf == query.state => {}
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +191,6 @@ pub async fn google_callback(
|
|||||||
|
|
||||||
if is_mobile {
|
if is_mobile {
|
||||||
let token = make_auth_token(user.id);
|
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 deep_link = format!("com.arrelin.family-budget-android://auth?token={}", token);
|
||||||
let html = format!(
|
let html = format!(
|
||||||
r#"<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0;url={0}"></head><body><script>window.location="{0}"</script></body></html>"#,
|
r#"<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0;url={0}"></head><body><script>window.location="{0}"</script></body></html>"#,
|
||||||
@@ -238,15 +231,7 @@ pub async fn mobile_callback(
|
|||||||
State(db): State<DatabaseConnection>,
|
State(db): State<DatabaseConnection>,
|
||||||
Query(query): Query<MobileCallbackQuery>,
|
Query(query): Query<MobileCallbackQuery>,
|
||||||
) -> Result<Json<serde_json::Value>, StatusCode> {
|
) -> Result<Json<serde_json::Value>, StatusCode> {
|
||||||
info!("mobile_callback: received token_prefix={}", &query.token[..query.token.len().min(20)]);
|
let user_id = verify_auth_token(&query.token).ok_or(StatusCode::UNAUTHORIZED)?;
|
||||||
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)
|
let user = User::find_by_id(user_id)
|
||||||
.one(&db)
|
.one(&db)
|
||||||
|
|||||||
@@ -30,20 +30,18 @@ export default function Login() {
|
|||||||
try {
|
try {
|
||||||
token = new URL(url).searchParams.get('token');
|
token = new URL(url).searchParams.get('token');
|
||||||
} catch {
|
} catch {
|
||||||
setError(t('login.authError'));
|
setError(t('login.error'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!token) { setError(t('login.authError')); return; }
|
if (!token) { setError(t('login.error')); return; }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
await authApi.mobileCallback(token);
|
await authApi.mobileCallback(token);
|
||||||
const me = await authApi.me();
|
const me = await authApi.me();
|
||||||
setUser(me.data);
|
setUser(me.data);
|
||||||
} catch (err: any) {
|
} catch {
|
||||||
const status = err?.response?.status;
|
setError(t('login.error'));
|
||||||
const msg = err?.response?.data ? JSON.stringify(err.response.data) : err?.message;
|
|
||||||
setError(`${status ?? 'network'}: ${msg}`);
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,20 +12,6 @@ export default defineConfig({
|
|||||||
? 'https://family-budget.duckdns.org'
|
? 'https://family-budget.duckdns.org'
|
||||||
: 'http://localhost:8080',
|
: 'http://localhost:8080',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
configure: (proxy) => {
|
|
||||||
if (process.env.TAURI_DEV_HOST) {
|
|
||||||
proxy.on('proxyRes', (proxyRes) => {
|
|
||||||
const cookies = proxyRes.headers['set-cookie'];
|
|
||||||
if (cookies) {
|
|
||||||
proxyRes.headers['set-cookie'] = cookies.map(cookie =>
|
|
||||||
cookie
|
|
||||||
.replace(/;\s*Secure/gi, '')
|
|
||||||
.replace(/;\s*Domain=[^;]*/gi, '')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "npm run dev --prefix ../frontend",
|
"beforeDevCommand": "npm run dev --prefix ../frontend",
|
||||||
"devUrl": "http://localhost:5173",
|
"devUrl": "http://localhost:5173",
|
||||||
"beforeBuildCommand": "VITE_API_BASE_URL=https://family-budget.duckdns.org/api npm run build --prefix ../frontend",
|
"beforeBuildCommand": "npm run build --prefix ../frontend",
|
||||||
"frontendDist": "../frontend/dist"
|
"frontendDist": "../frontend/dist"
|
||||||
},
|
},
|
||||||
"app": {
|
"app": {
|
||||||
|
|||||||
Reference in New Issue
Block a user