Add authentication from upstream providers #107
@ -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<Addr<ProvidersStatesActor>>,
|
||||
query: web::Query<StartLoginQuery>,
|
||||
logger: ActionLogger,
|
||||
id: Option<Identity>,
|
||||
) -> 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<Arc<ProvidersManager>>,
|
||||
@ -133,7 +142,14 @@ pub async fn finish_login(
|
||||
bruteforce: web::Data<Addr<BruteForceActor>>,
|
||||
query: web::Query<FinishLoginQuery>,
|
||||
logger: ActionLogger,
|
||||
id: Option<Identity>,
|
||||
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()))
|
||||
}
|
||||
|
@ -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!(
|
||||
|
Loading…
Reference in New Issue
Block a user