From 24027ed3c5224fae15e050754c33a5e71b0480ce Mon Sep 17 00:00:00 2001 From: Chris Jean-Marie Date: Sun, 22 Sep 2024 12:05:07 +0000 Subject: [PATCH] Fix Google authentication --- backend/.env | 3 + backend/db/.gitkeep | 0 backend/db/db.sqlite3 | Bin 0 -> 32768 bytes backend/src/google_oauth.rs | 2 +- backend/src/main.rs | 111 ++++++++++-------------------------- backend/src/oauth.rs | 5 +- 6 files changed, 37 insertions(+), 84 deletions(-) create mode 100644 backend/.env create mode 100644 backend/db/.gitkeep create mode 100644 backend/db/db.sqlite3 diff --git a/backend/.env b/backend/.env new file mode 100644 index 0000000..1f95035 --- /dev/null +++ b/backend/.env @@ -0,0 +1,3 @@ +DATABASE_URL=sqlite://db/db.sqlite3 +GOOGLE_CLIENT_ID=735264084619-clsmvgdqdmum4rvrcj0kuk28k9agir1c.apps.googleusercontent.com +GOOGLE_CLIENT_SECRET=L6uI7FQGoMJd-ay1HO_iGJ6M \ No newline at end of file diff --git a/backend/db/.gitkeep b/backend/db/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/backend/db/db.sqlite3 b/backend/db/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..c5f41e13ed716cd175fbd6356b91e50c9ac611ce GIT binary patch literal 32768 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 literal 0 HcmV?d00001 diff --git a/backend/src/google_oauth.rs b/backend/src/google_oauth.rs index 99a43fe..72994e6 100644 --- a/backend/src/google_oauth.rs +++ b/backend/src/google_oauth.rs @@ -91,7 +91,7 @@ pub fn google_oauth_client() -> BasicClient { } let redirect_url = env::var("REDIRECT_URL") - .unwrap_or_else(|_| "http://localhost:40192/auth/google".to_string()); + .unwrap_or_else(|_| "http://localhost:40192/google_auth_return".to_string()); // .unwrap_or_else(|_| "https://www.jean-marie.ca/auth/google".to_string()); let google_client_id = env::var("GOOGLE_CLIENT_ID").expect("Missing GOOGLE_CLIENT_ID!"); diff --git a/backend/src/main.rs b/backend/src/main.rs index 17fbfde..69596c5 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -1,25 +1,23 @@ use std::net::SocketAddr; use askama::Template; -use axum_session::{Session, SessionAnyPool, SessionConfig, SessionStore, SessionLayer}; use axum::{ - Router, - routing::{get, get_service}, response::{Html, IntoResponse, Response}, + extract::{FromRef, State}, middleware, response::{Html, IntoResponse, Redirect, Response}, routing::{get, get_service}, Extension, Router }; -use axum_extra::extract::cookie::PrivateCookieJar; -use http::StatusCode; -use serde::{Serialize, Deserialize}; +use axum_extra::TypedHeader; +use headers::Cookie; +use http::{Request, StatusCode}; use sqlx::{sqlite::SqlitePoolOptions, SqlitePool}; use tower_http::services::ServeDir; mod error_handling; +use middlewares::{check_auth, inject_user_data}; mod google_oauth; mod middlewares; mod oauth; use error_handling::AppError; use google_oauth::*; -use middlewares::{check_auth, inject_user_data}; -use oauth::{login, logout, oauth_return}; +use oauth::{login, logout, google_auth_return}; struct HtmlTemplate(T); @@ -53,13 +51,6 @@ struct LoginTemplate { name: String, } -#[derive(Template)] -#[template(path = "dashboard.html")] -struct DashboardTemplate { - logged_in: bool, - name: String, -} - #[derive(Clone)] pub struct AppState { pub db_pool: SqlitePool, @@ -70,62 +61,41 @@ pub struct UserData { #[allow(dead_code)] pub user_id: i64, pub user_email: String, -} - -#[derive(Debug, Serialize, Deserialize)] -struct User { - id: String, - avatar: Option, - username: String, - discriminator: String, -} +/* pub user_name: String, + pub user_discriminator: String, + pub user_avatar: String, + pub user_access_token: String, + pub user_refresh_token: String, + pub user_expires_at: i64, + */} #[tokio::main] async fn main() { // initialize tracing tracing_subscriber::fmt::init(); - let session_config = SessionConfig::default() - .with_table_name("sessions"); - - //let session_store = SessionStore::::new(None, session_config).await.unwrap(); - let db_pool = SqlitePoolOptions::new() .max_connections(5) .connect("sqlite://db/db.sqlite3") - .await - .map_err(|e| format!("DB connection failed: {}", e))?; + .await; - let app_state = AppState { - db_pool: db_pool - }; + let app_state = AppState {db_pool: db_pool.expect("Failed to get db_pool") }; - // Create HashMap to store oauth configurations - // let mut oauth_clients = HashMap::<&str, BasicClient>::new(); - - // Get the client structures - // let facebook_oauth_client = facebook_oauth_client(); - // let discord_oauth_client = discord_oauth_client(); - // let google_oauth_client = google_oauth_client(); - - // Get oauth clients for the hashmap - // oauth_clients.insert("Facebook", facebook_oauth_client); - // oauth_clients.insert("Discord", discord_oauth_client); - // oauth_clients.insert("Google", google_oauth_client); + let user_data: Option = None; // build our application with some routes let app = Router::new() .nest_service("/assets", ServeDir::new("templates/assets") .fallback(get_service(ServeDir::new("templates/assets")))) + .route_layer(middleware::from_fn_with_state(app_state.clone(), check_auth)) .route("/", get(index)) - .route("/dashboard", get(dashboard)) .route("/login", get(login)) - .route("/google_auth", get(google_auth)) - .route("/auth/google", get(google_authorized)) .route("/logout", get(logout)) - //.layer(SessionLayer::new(session_store)) - .with_state(app_state) - // .layer(Extension(oauth_clients)); + .route("/google_auth", get(google_auth)) + .route("/google_auth_return", get(google_auth_return)) + .route_layer(middleware::from_fn_with_state(app_state.db_pool.clone(), inject_user_data)) + .with_state(app_state.db_pool) + .layer(Extension(user_data)) ; // run it @@ -137,36 +107,15 @@ async fn main() { .unwrap(); } -async fn index(session: Session) -> impl IntoResponse { - let logged_in = session.get("logged_in").unwrap_or(false); - let name = session.get("name").unwrap_or("You're not logged in.".to_string()); +async fn index( + Extension(user_data): Extension>, + request: Request, +) -> impl IntoResponse { + let user_email = user_data.map(|s| s.user_email); + let login_return_url = "?return_url=".to_owned() + &*request.uri().to_string(); + let logged_in = user_email.is_some(); + let name = user_email.unwrap_or_default(); let template = IndexTemplate { logged_in, name}; HtmlTemplate(template) } - -/* async fn login(session: Session) -> impl IntoResponse { - let logged_in = session.get("logged_in").unwrap_or(false); - let name = session.get("name").unwrap_or("".to_string()); - - session.set_store(true); - - session.set("logged_in", logged_in); - session.set("name", &name); - - let template = LoginTemplate { logged_in, name }; - HtmlTemplate(template) -} */ - -async fn dashboard(session: Session) -> impl IntoResponse { - let logged_in = session.get("logged_in").unwrap_or(false); - let name = session.get("name").unwrap_or("".to_string()); - - session.set_store(true); - - session.set("logged_in", logged_in); - session.set("name", &name); - - let template = DashboardTemplate { logged_in, name }; - HtmlTemplate(template) -} \ No newline at end of file diff --git a/backend/src/oauth.rs b/backend/src/oauth.rs index 155e20e..aae4871 100644 --- a/backend/src/oauth.rs +++ b/backend/src/oauth.rs @@ -38,7 +38,7 @@ fn get_client(hostname: String) -> Result { "https" }; - let redirect_url = format!("{}://{}/oauth_return", protocol, hostname); + let redirect_url = format!("{}://{}/google_auth_return", protocol, hostname); // Set up the config for the Google OAuth2 process. let client = BasicClient::new( @@ -61,6 +61,7 @@ pub async fn login( State(db_pool): State, Host(hostname): Host, ) -> Result { + if user_data.is_some() { // check if already authenticated return Ok(Redirect::to("/")); @@ -95,7 +96,7 @@ pub async fn login( Ok(Redirect::to(authorize_url.as_str())) } -pub async fn oauth_return( +pub async fn google_auth_return( Query(mut params): Query>, State(db_pool): State, Host(hostname): Host,