Handle errors cases when retrieving login token & rate limiting
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
bee794a589
commit
b26e283f7d
@ -4,9 +4,10 @@ use actix::Addr;
|
|||||||
use actix_web::{web, HttpResponse, Responder};
|
use actix_web::{web, HttpResponse, Responder};
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
|
|
||||||
use crate::actors::providers_states_actor;
|
use crate::actors::bruteforce_actor::BruteForceActor;
|
||||||
use crate::actors::providers_states_actor::{ProviderLoginState, ProvidersStatesActor};
|
use crate::actors::providers_states_actor::{ProviderLoginState, ProvidersStatesActor};
|
||||||
use crate::constants::APP_NAME;
|
use crate::actors::{bruteforce_actor, providers_states_actor};
|
||||||
|
use crate::constants::{APP_NAME, MAX_FAILED_LOGIN_ATTEMPTS};
|
||||||
use crate::controllers::base_controller::{build_fatal_error_page, redirect_user};
|
use crate::controllers::base_controller::{build_fatal_error_page, redirect_user};
|
||||||
use crate::controllers::login_controller::BaseLoginPage;
|
use crate::controllers::login_controller::BaseLoginPage;
|
||||||
use crate::data::action_logger::{Action, ActionLogger};
|
use crate::data::action_logger::{Action, ActionLogger};
|
||||||
@ -127,6 +128,7 @@ pub async fn finish_login(
|
|||||||
remote_ip: RemoteIP,
|
remote_ip: RemoteIP,
|
||||||
providers: web::Data<Arc<ProvidersManager>>,
|
providers: web::Data<Arc<ProvidersManager>>,
|
||||||
states: web::Data<Addr<ProvidersStatesActor>>,
|
states: web::Data<Addr<ProvidersStatesActor>>,
|
||||||
|
bruteforce: web::Data<Addr<BruteForceActor>>,
|
||||||
query: web::Query<FinishLoginQuery>,
|
query: web::Query<FinishLoginQuery>,
|
||||||
logger: ActionLogger,
|
logger: ActionLogger,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
@ -167,6 +169,21 @@ pub async fn finish_login(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We perform rate limiting before attempting to use authorization code
|
||||||
|
let failed_attempts = bruteforce
|
||||||
|
.send(bruteforce_actor::CountFailedAttempt {
|
||||||
|
ip: remote_ip.into(),
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if failed_attempts > MAX_FAILED_LOGIN_ATTEMPTS {
|
||||||
|
logger.log(Action::ProviderRateLimited);
|
||||||
|
return HttpResponse::TooManyRequests().body(build_fatal_error_page(
|
||||||
|
"Too many failed login attempts, please try again later!",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// Retrieve provider information & configuration
|
// Retrieve provider information & configuration
|
||||||
let provider = providers
|
let provider = providers
|
||||||
.find_by_id(&state.provider_id)
|
.find_by_id(&state.provider_id)
|
||||||
@ -182,11 +199,33 @@ pub async fn finish_login(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO : rate limiting
|
|
||||||
|
|
||||||
// Get access token & user information
|
// Get access token & user information
|
||||||
let token = provider_config.get_token(&provider, &query.code).await;
|
let token = provider_config.get_token(&provider, &query.code).await;
|
||||||
log::debug!("{:#?}", token);
|
let token = match token {
|
||||||
|
Ok(t) => t,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Failed to retrieve login token! {:?}", e);
|
||||||
|
|
||||||
|
bruteforce
|
||||||
|
.send(bruteforce_actor::RecordFailedAttempt {
|
||||||
|
ip: remote_ip.into(),
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
logger.log(Action::ProviderFailedGetToken {
|
||||||
|
state: &state,
|
||||||
|
code: query.code.as_str(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return ProviderLoginError::get(
|
||||||
|
"Failed to retrieve login token from identity provider!",
|
||||||
|
&state.redirect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("go on {:?}", token);
|
||||||
|
|
||||||
// TODO : check token signature
|
// TODO : check token signature
|
||||||
// TODO : check if user is authorized to access application
|
// TODO : check if user is authorized to access application
|
||||||
|
@ -7,6 +7,7 @@ use actix_identity::Identity;
|
|||||||
use actix_web::dev::Payload;
|
use actix_web::dev::Payload;
|
||||||
use actix_web::{web, Error, FromRequest, HttpRequest};
|
use actix_web::{web, Error, FromRequest, HttpRequest};
|
||||||
|
|
||||||
|
use crate::actors::providers_states_actor::ProviderLoginState;
|
||||||
use crate::actors::users_actor;
|
use crate::actors::users_actor;
|
||||||
use crate::actors::users_actor::{AuthorizedAuthenticationSources, UsersActor};
|
use crate::actors::users_actor::{AuthorizedAuthenticationSources, UsersActor};
|
||||||
use crate::data::client::Client;
|
use crate::data::client::Client;
|
||||||
@ -38,6 +39,11 @@ pub enum Action<'a> {
|
|||||||
ProviderCBInvalidState {
|
ProviderCBInvalidState {
|
||||||
state: &'a str,
|
state: &'a str,
|
||||||
},
|
},
|
||||||
|
ProviderRateLimited,
|
||||||
|
ProviderFailedGetToken {
|
||||||
|
state: &'a ProviderLoginState,
|
||||||
|
code: &'a str,
|
||||||
|
},
|
||||||
Signout,
|
Signout,
|
||||||
UserNeed2FAOnLogin(&'a User),
|
UserNeed2FAOnLogin(&'a User),
|
||||||
UserSuccessfullyAuthenticated(&'a User),
|
UserSuccessfullyAuthenticated(&'a User),
|
||||||
@ -108,6 +114,8 @@ impl<'a> Action<'a> {
|
|||||||
format!("failed provider authentication with message '{message}'"),
|
format!("failed provider authentication with message '{message}'"),
|
||||||
Action::ProviderCBInvalidState { state } =>
|
Action::ProviderCBInvalidState { state } =>
|
||||||
format!("provided invalid callback state after provider authentication: '{state}'"),
|
format!("provided invalid callback state after provider authentication: '{state}'"),
|
||||||
|
Action::ProviderRateLimited => "could not complete OpenID login because it has reached failed attempts rate limit!".to_string(),
|
||||||
|
Action::ProviderFailedGetToken {state, code} => format!("could not complete login from provider because the id_token could not be retrieved! (state={:?} code = {code})",state),
|
||||||
Action::Signout => "signed out".to_string(),
|
Action::Signout => "signed out".to_string(),
|
||||||
Action::UserNeed2FAOnLogin(user) => {
|
Action::UserNeed2FAOnLogin(user) => {
|
||||||
format!(
|
format!(
|
||||||
|
Loading…
Reference in New Issue
Block a user