Make usage of FatalErrorPage
more convenient
This commit is contained in:
parent
a516f173ad
commit
48112dfed7
@ -24,9 +24,9 @@ Features :
|
|||||||
* [x] `authorization_code` flow
|
* [x] `authorization_code` flow
|
||||||
* [x] Client authentication using secrets
|
* [x] Client authentication using secrets
|
||||||
* [x] Bruteforce protection
|
* [x] Bruteforce protection
|
||||||
* [ ] 2 factors authentication
|
* [x] 2 factor authentication
|
||||||
* [x] TOTP (authenticator app)
|
* [x] TOTP (authenticator app)
|
||||||
* [x] Using a security key
|
* [x] Using a security key (Webauthn)
|
||||||
* [ ] Fully responsive webui
|
* [ ] Fully responsive webui
|
||||||
* [ ] `robots.txt` file to prevent indexing
|
* [ ] `robots.txt` file to prevent indexing
|
||||||
|
|
||||||
|
@ -29,6 +29,10 @@ pub fn redirect_user_for_login<P: Display>(redirect_uri: P) -> HttpResponse {
|
|||||||
/// Fatal error page message
|
/// Fatal error page message
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "fatal_error.html")]
|
#[template(path = "fatal_error.html")]
|
||||||
pub struct FatalErrorPage {
|
struct FatalErrorPage {
|
||||||
pub message: &'static str,
|
message: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_fatal_error_page(msg: &'static str) -> String {
|
||||||
|
FatalErrorPage { message: msg }.render().unwrap()
|
||||||
}
|
}
|
@ -7,7 +7,7 @@ use crate::actors::{bruteforce_actor, users_actor};
|
|||||||
use crate::actors::bruteforce_actor::BruteForceActor;
|
use crate::actors::bruteforce_actor::BruteForceActor;
|
||||||
use crate::actors::users_actor::{ChangePasswordResult, LoginResult, UsersActor};
|
use crate::actors::users_actor::{ChangePasswordResult, LoginResult, UsersActor};
|
||||||
use crate::constants::{APP_NAME, MAX_FAILED_LOGIN_ATTEMPTS, MIN_PASS_LEN};
|
use crate::constants::{APP_NAME, MAX_FAILED_LOGIN_ATTEMPTS, MIN_PASS_LEN};
|
||||||
use crate::controllers::base_controller::{FatalErrorPage, redirect_user, redirect_user_for_login};
|
use crate::controllers::base_controller::{build_fatal_error_page, redirect_user, redirect_user_for_login};
|
||||||
use crate::data::login_redirect::LoginRedirect;
|
use crate::data::login_redirect::LoginRedirect;
|
||||||
use crate::data::remote_ip::RemoteIP;
|
use crate::data::remote_ip::RemoteIP;
|
||||||
use crate::data::session_identity::{SessionIdentity, SessionStatus};
|
use crate::data::session_identity::{SessionIdentity, SessionStatus};
|
||||||
@ -91,9 +91,7 @@ pub async fn login_route(
|
|||||||
|
|
||||||
if failed_attempts > MAX_FAILED_LOGIN_ATTEMPTS {
|
if failed_attempts > MAX_FAILED_LOGIN_ATTEMPTS {
|
||||||
return HttpResponse::TooManyRequests().body(
|
return HttpResponse::TooManyRequests().body(
|
||||||
FatalErrorPage {
|
build_fatal_error_page("Too many failed login attempts, please try again later!")
|
||||||
message: "Too many failed login attempts, please try again later!"
|
|
||||||
}.render().unwrap()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,15 +304,13 @@ pub async fn login_with_otp(id: Identity, query: web::Query<LoginWithOTPQuery>,
|
|||||||
|
|
||||||
let factor = match user.find_factor(&query.id) {
|
let factor = match user.find_factor(&query.id) {
|
||||||
Some(f) => f,
|
Some(f) => f,
|
||||||
None => return HttpResponse::Ok()
|
None => return HttpResponse::Ok().body(build_fatal_error_page("Factor not found!"))
|
||||||
.body(FatalErrorPage { message: "Factor not found!" }.render().unwrap())
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let key = match &factor.kind {
|
let key = match &factor.kind {
|
||||||
TwoFactorType::TOTP(key) => key,
|
TwoFactorType::TOTP(key) => key,
|
||||||
_ => {
|
_ => {
|
||||||
return HttpResponse::Ok()
|
return HttpResponse::Ok().body(build_fatal_error_page("Factor is not a TOTP key!"));
|
||||||
.body(FatalErrorPage { message: "Factor is not a TOTP key!" }.render().unwrap());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -360,15 +356,14 @@ pub async fn login_with_webauthn(id: Identity, query: web::Query<LoginWithWebaut
|
|||||||
|
|
||||||
let factor = match user.find_factor(&query.id) {
|
let factor = match user.find_factor(&query.id) {
|
||||||
Some(f) => f,
|
Some(f) => f,
|
||||||
None => return HttpResponse::Ok()
|
None => return HttpResponse::Ok().body(build_fatal_error_page("Factor not found!"))
|
||||||
.body(FatalErrorPage { message: "Factor not found!" }.render().unwrap())
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let key = match &factor.kind {
|
let key = match &factor.kind {
|
||||||
TwoFactorType::WEBAUTHN(key) => key,
|
TwoFactorType::WEBAUTHN(key) => key,
|
||||||
_ => {
|
_ => {
|
||||||
return HttpResponse::Ok()
|
return HttpResponse::Ok()
|
||||||
.body(FatalErrorPage { message: "Factor is not a Webauthn key!" }.render().unwrap());
|
.body(build_fatal_error_page("Factor is not a Webauthn key!"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -377,7 +372,7 @@ pub async fn login_with_webauthn(id: Identity, query: web::Query<LoginWithWebaut
|
|||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to generate webauthn challenge! {:?}", e);
|
log::error!("Failed to generate webauthn challenge! {:?}", e);
|
||||||
return HttpResponse::InternalServerError()
|
return HttpResponse::InternalServerError()
|
||||||
.body(FatalErrorPage { message: "Failed to generate webauthn challenge" }.render().unwrap());
|
.body(build_fatal_error_page("Failed to generate webauthn challenge"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,13 +4,12 @@ use actix::Addr;
|
|||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
use actix_web::{HttpRequest, HttpResponse, Responder, web};
|
use actix_web::{HttpRequest, HttpResponse, Responder, web};
|
||||||
use actix_web::error::ErrorUnauthorized;
|
use actix_web::error::ErrorUnauthorized;
|
||||||
use askama::Template;
|
|
||||||
|
|
||||||
use crate::actors::{openid_sessions_actor, users_actor};
|
use crate::actors::{openid_sessions_actor, users_actor};
|
||||||
use crate::actors::openid_sessions_actor::{OpenIDSessionsActor, Session, SessionID};
|
use crate::actors::openid_sessions_actor::{OpenIDSessionsActor, Session, SessionID};
|
||||||
use crate::actors::users_actor::UsersActor;
|
use crate::actors::users_actor::UsersActor;
|
||||||
use crate::constants::*;
|
use crate::constants::*;
|
||||||
use crate::controllers::base_controller::FatalErrorPage;
|
use crate::controllers::base_controller::build_fatal_error_page;
|
||||||
use crate::data::app_config::AppConfig;
|
use crate::data::app_config::AppConfig;
|
||||||
use crate::data::client::{ClientID, ClientManager};
|
use crate::data::client::{ClientID, ClientManager};
|
||||||
use crate::data::code_challenge::CodeChallenge;
|
use crate::data::code_challenge::CodeChallenge;
|
||||||
@ -100,18 +99,16 @@ pub async fn authorize(user: CurrentUser, id: Identity, query: web::Query<Author
|
|||||||
sessions: web::Data<Addr<OpenIDSessionsActor>>) -> impl Responder {
|
sessions: web::Data<Addr<OpenIDSessionsActor>>) -> impl Responder {
|
||||||
let client = match clients.find_by_id(&query.client_id) {
|
let client = match clients.find_by_id(&query.client_id) {
|
||||||
None => {
|
None => {
|
||||||
return HttpResponse::BadRequest().body(FatalErrorPage {
|
return HttpResponse::BadRequest()
|
||||||
message: "Client is invalid!"
|
.body(build_fatal_error_page("Client is invalid!"));
|
||||||
}.render().unwrap());
|
|
||||||
}
|
}
|
||||||
Some(c) => c
|
Some(c) => c
|
||||||
};
|
};
|
||||||
|
|
||||||
let redirect_uri = query.redirect_uri.trim().to_string();
|
let redirect_uri = query.redirect_uri.trim().to_string();
|
||||||
if !redirect_uri.starts_with(&client.redirect_uri) {
|
if !redirect_uri.starts_with(&client.redirect_uri) {
|
||||||
return HttpResponse::BadRequest().body(FatalErrorPage {
|
return HttpResponse::BadRequest()
|
||||||
message: "Redirect URI is invalid!"
|
.body(build_fatal_error_page("Redirect URI is invalid!"));
|
||||||
}.render().unwrap());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !query.scope.split(' ').any(|x| x == "openid") {
|
if !query.scope.split(' ').any(|x| x == "openid") {
|
||||||
|
@ -11,10 +11,9 @@ use actix_web::{
|
|||||||
};
|
};
|
||||||
use actix_web::body::EitherBody;
|
use actix_web::body::EitherBody;
|
||||||
use actix_web::http::{header, Method};
|
use actix_web::http::{header, Method};
|
||||||
use askama::Template;
|
|
||||||
|
|
||||||
use crate::constants::{ADMIN_ROUTES, AUTHENTICATED_ROUTES, AUTHORIZE_URI, TOKEN_URI, USERINFO_URI};
|
use crate::constants::{ADMIN_ROUTES, AUTHENTICATED_ROUTES, AUTHORIZE_URI, TOKEN_URI, USERINFO_URI};
|
||||||
use crate::controllers::base_controller::{FatalErrorPage, redirect_user_for_login};
|
use crate::controllers::base_controller::{build_fatal_error_page, redirect_user_for_login};
|
||||||
use crate::data::app_config::AppConfig;
|
use crate::data::app_config::AppConfig;
|
||||||
use crate::data::session_identity::{SessionIdentity, SessionIdentityData, SessionStatus};
|
use crate::data::session_identity::{SessionIdentity, SessionIdentityData, SessionStatus};
|
||||||
|
|
||||||
@ -143,10 +142,8 @@ impl<S, B> Service<ServiceRequest> for AuthInnerMiddleware<S>
|
|||||||
if !session.is_admin() && req.path().starts_with(ADMIN_ROUTES) {
|
if !session.is_admin() && req.path().starts_with(ADMIN_ROUTES) {
|
||||||
return Ok(req
|
return Ok(req
|
||||||
.into_response(
|
.into_response(
|
||||||
HttpResponse::Unauthorized()
|
HttpResponse::Unauthorized().body(
|
||||||
.body(FatalErrorPage {
|
build_fatal_error_page("You are not allowed to access this resource.")),
|
||||||
message: "You are not allowed to access this resource."
|
|
||||||
}.render().unwrap()),
|
|
||||||
)
|
)
|
||||||
.map_into_right_body());
|
.map_into_right_body());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user