diff --git a/src/controllers/providers_controller.rs b/src/controllers/providers_controller.rs index 8daebce..f067ad7 100644 --- a/src/controllers/providers_controller.rs +++ b/src/controllers/providers_controller.rs @@ -1,7 +1,8 @@ use std::sync::Arc; use actix::Addr; -use actix_web::{web, HttpResponse, Responder}; +use actix_identity::Identity; +use actix_web::{web, HttpRequest, HttpResponse, Responder}; use askama::Template; use crate::actors::bruteforce_actor::BruteForceActor; @@ -16,6 +17,7 @@ use crate::data::login_redirect::LoginRedirect; use crate::data::provider::{ProviderID, ProvidersManager}; use crate::data::provider_configuration::ProviderConfigurationHelper; use crate::data::remote_ip::RemoteIP; +use crate::data::session_identity::{SessionIdentity, SessionStatus}; #[derive(askama::Template)] #[template(path = "login/prov_login_error.html")] @@ -59,7 +61,13 @@ pub async fn start_login( states: web::Data>, query: web::Query, logger: ActionLogger, + id: Option, ) -> impl Responder { + // Check if user is already authenticated + if SessionIdentity(id.as_ref()).is_authenticated() { + return redirect_user(query.redirect.get()); + } + // Get provider information let provider = match providers.find_by_id(&query.id) { None => { @@ -125,6 +133,7 @@ pub struct FinishLoginQuery { } /// Finish user authentication using a provider +#[allow(clippy::too_many_arguments)] pub async fn finish_login( remote_ip: RemoteIP, providers: web::Data>, @@ -133,7 +142,14 @@ pub async fn finish_login( bruteforce: web::Data>, query: web::Query, logger: ActionLogger, + id: Option, + http_req: HttpRequest, ) -> impl Responder { + // Check if user is already authenticated + if SessionIdentity(id.as_ref()).is_authenticated() { + return redirect_user("/"); + } + let query = match query.0.success { Some(q) => q, None => { @@ -339,10 +355,19 @@ pub async fn finish_login( } }; - log::info!("user={:#?}", user); + logger.log(Action::ProviderLoginSuccessful { + provider: &provider, + user: &user, + }); - // TODO : check if 2FA is enabled - // TODO : redirect user to login route - // TODO : add proper logging - HttpResponse::Ok().body("continue") + let status = if user.has_two_factor() && !user.can_bypass_two_factors_for_ip(remote_ip.0) { + logger.log(Action::UserNeed2FAOnLogin(&user)); + SessionStatus::Need2FA + } else { + logger.log(Action::UserSuccessfullyAuthenticated(&user)); + SessionStatus::SignedIn + }; + + SessionIdentity(id.as_ref()).set_user(&http_req, &user, status); + redirect_user(&format!("/login?redirect={}", state.redirect.get_encoded())) } diff --git a/src/data/action_logger.rs b/src/data/action_logger.rs index 4439952..694d074 100644 --- a/src/data/action_logger.rs +++ b/src/data/action_logger.rs @@ -70,6 +70,10 @@ pub enum Action<'a> { provider: &'a Provider, email: &'a str, }, + ProviderLoginSuccessful { + provider: &'a Provider, + user: &'a User, + }, Signout, UserNeed2FAOnLogin(&'a User), UserSuccessfullyAuthenticated(&'a User), @@ -153,6 +157,8 @@ impl<'a> Action<'a> { format!("could not login using provider {} because the account associated to the email {email} is not allowed to authenticate using this provider!", &provider.id.0), Action::ProviderLoginFailed { provider, email } => format!("could not login using provider {} with the email {email} for an unknown reason!", &provider.id.0), + Action::ProviderLoginSuccessful {provider, user} => + format!("successfully authenticated using provider {} as {}", provider.id.0, user.quick_identity()), Action::Signout => "signed out".to_string(), Action::UserNeed2FAOnLogin(user) => { format!(