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 askama::Template;
|
||||
|
||||
use crate::actors::providers_states_actor;
|
||||
use crate::actors::bruteforce_actor::BruteForceActor;
|
||||
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::login_controller::BaseLoginPage;
|
||||
use crate::data::action_logger::{Action, ActionLogger};
|
||||
@ -127,6 +128,7 @@ pub async fn finish_login(
|
||||
remote_ip: RemoteIP,
|
||||
providers: web::Data<Arc<ProvidersManager>>,
|
||||
states: web::Data<Addr<ProvidersStatesActor>>,
|
||||
bruteforce: web::Data<Addr<BruteForceActor>>,
|
||||
query: web::Query<FinishLoginQuery>,
|
||||
logger: ActionLogger,
|
||||
) -> 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
|
||||
let provider = providers
|
||||
.find_by_id(&state.provider_id)
|
||||
@ -182,11 +199,33 @@ pub async fn finish_login(
|
||||
}
|
||||
};
|
||||
|
||||
// TODO : rate limiting
|
||||
|
||||
// Get access token & user information
|
||||
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 if user is authorized to access application
|
||||
|
@ -7,6 +7,7 @@ use actix_identity::Identity;
|
||||
use actix_web::dev::Payload;
|
||||
use actix_web::{web, Error, FromRequest, HttpRequest};
|
||||
|
||||
use crate::actors::providers_states_actor::ProviderLoginState;
|
||||
use crate::actors::users_actor;
|
||||
use crate::actors::users_actor::{AuthorizedAuthenticationSources, UsersActor};
|
||||
use crate::data::client::Client;
|
||||
@ -38,6 +39,11 @@ pub enum Action<'a> {
|
||||
ProviderCBInvalidState {
|
||||
state: &'a str,
|
||||
},
|
||||
ProviderRateLimited,
|
||||
ProviderFailedGetToken {
|
||||
state: &'a ProviderLoginState,
|
||||
code: &'a str,
|
||||
},
|
||||
Signout,
|
||||
UserNeed2FAOnLogin(&'a User),
|
||||
UserSuccessfullyAuthenticated(&'a User),
|
||||
@ -108,6 +114,8 @@ impl<'a> Action<'a> {
|
||||
format!("failed provider authentication with message '{message}'"),
|
||||
Action::ProviderCBInvalidState { 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::UserNeed2FAOnLogin(user) => {
|
||||
format!(
|
||||
|
Loading…
Reference in New Issue
Block a user