2022-07-22 10:21:38 +00:00
|
|
|
use core::time::Duration;
|
2022-04-20 19:06:53 +00:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
2022-04-02 13:44:09 +00:00
|
|
|
use actix::Actor;
|
2022-07-22 10:21:38 +00:00
|
|
|
use actix_identity::config::LogoutBehaviour;
|
|
|
|
use actix_identity::IdentityMiddleware;
|
|
|
|
use actix_session::storage::CookieSessionStore;
|
2022-11-11 11:26:02 +00:00
|
|
|
use actix_session::SessionMiddleware;
|
2022-07-22 10:21:38 +00:00
|
|
|
use actix_web::cookie::{Key, SameSite};
|
2022-03-30 08:29:10 +00:00
|
|
|
use actix_web::middleware::Logger;
|
2022-11-11 11:26:02 +00:00
|
|
|
use actix_web::{get, middleware, web, App, HttpResponse, HttpServer};
|
2022-03-29 17:32:31 +00:00
|
|
|
|
2022-04-03 14:45:25 +00:00
|
|
|
use basic_oidc::actors::bruteforce_actor::BruteForceActor;
|
2022-04-09 10:18:59 +00:00
|
|
|
use basic_oidc::actors::openid_sessions_actor::OpenIDSessionsActor;
|
2022-04-02 13:44:09 +00:00
|
|
|
use basic_oidc::actors::users_actor::UsersActor;
|
2022-04-07 15:57:10 +00:00
|
|
|
use basic_oidc::constants::*;
|
2022-03-30 08:14:39 +00:00
|
|
|
use basic_oidc::controllers::assets_controller::assets_route;
|
2022-11-11 11:26:02 +00:00
|
|
|
use basic_oidc::controllers::*;
|
2022-03-29 17:32:31 +00:00
|
|
|
use basic_oidc::data::app_config::AppConfig;
|
2022-04-06 15:18:06 +00:00
|
|
|
use basic_oidc::data::client::ClientManager;
|
2022-03-29 17:32:31 +00:00
|
|
|
use basic_oidc::data::entity_manager::EntityManager;
|
2022-04-13 17:07:58 +00:00
|
|
|
use basic_oidc::data::jwt_signer::JWTSigner;
|
2022-03-29 17:32:31 +00:00
|
|
|
use basic_oidc::data::user::{hash_password, User};
|
2022-04-20 19:06:53 +00:00
|
|
|
use basic_oidc::data::webauthn_manager::WebAuthManager;
|
2022-04-02 13:44:09 +00:00
|
|
|
use basic_oidc::middlewares::auth_middleware::AuthMiddleware;
|
2022-03-29 17:32:31 +00:00
|
|
|
|
|
|
|
#[get("/health")]
|
2022-03-30 08:14:39 +00:00
|
|
|
async fn health() -> &'static str {
|
2022-03-29 17:32:31 +00:00
|
|
|
"Running"
|
2022-03-29 16:19:23 +00:00
|
|
|
}
|
2022-03-29 17:32:31 +00:00
|
|
|
|
2022-03-30 08:14:39 +00:00
|
|
|
#[actix_web::main]
|
|
|
|
async fn main() -> std::io::Result<()> {
|
|
|
|
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
2022-03-29 17:32:31 +00:00
|
|
|
|
2022-11-12 16:01:45 +00:00
|
|
|
let config = AppConfig::get();
|
2022-03-29 17:32:31 +00:00
|
|
|
|
|
|
|
if !config.storage_path().exists() {
|
2022-03-30 06:42:18 +00:00
|
|
|
log::error!(
|
|
|
|
"Specified storage path {:?} does not exists!",
|
|
|
|
config.storage_path()
|
|
|
|
);
|
2022-03-29 17:32:31 +00:00
|
|
|
panic!()
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut users = EntityManager::<User>::open_or_create(config.users_file())
|
|
|
|
.expect("Failed to load users list!");
|
|
|
|
|
|
|
|
// Create initial user if required
|
2022-03-30 06:42:18 +00:00
|
|
|
if users.is_empty() {
|
2022-03-29 17:32:31 +00:00
|
|
|
log::info!("Create default {} user", DEFAULT_ADMIN_USERNAME);
|
2022-03-30 06:42:18 +00:00
|
|
|
let default_admin = User {
|
|
|
|
username: DEFAULT_ADMIN_USERNAME.to_string(),
|
|
|
|
password: hash_password(DEFAULT_ADMIN_PASSWORD).unwrap(),
|
|
|
|
need_reset_password: true,
|
2022-04-07 15:32:29 +00:00
|
|
|
authorized_clients: None,
|
2022-03-30 06:42:18 +00:00
|
|
|
admin: true,
|
|
|
|
..Default::default()
|
|
|
|
};
|
|
|
|
|
|
|
|
users
|
|
|
|
.insert(default_admin)
|
2022-03-29 17:32:31 +00:00
|
|
|
.expect("Failed to create initial user!");
|
|
|
|
}
|
|
|
|
|
2022-03-30 09:40:03 +00:00
|
|
|
let users_actor = UsersActor::new(users).start();
|
2022-04-03 14:45:25 +00:00
|
|
|
let bruteforce_actor = BruteForceActor::default().start();
|
2022-04-09 10:18:59 +00:00
|
|
|
let openid_sessions_actor = OpenIDSessionsActor::default().start();
|
2022-11-11 11:26:02 +00:00
|
|
|
let jwt_signer = JWTSigner::gen_from_memory().expect("Failed to generate JWKS key");
|
2022-11-12 16:01:45 +00:00
|
|
|
let webauthn_manager = Arc::new(WebAuthManager::init(config));
|
2022-03-30 09:40:03 +00:00
|
|
|
|
2022-03-30 08:14:39 +00:00
|
|
|
log::info!("Server will listen on {}", config.listen_address);
|
2022-04-03 13:48:45 +00:00
|
|
|
let listen_address = config.listen_address.to_string();
|
2022-03-30 08:14:39 +00:00
|
|
|
|
2022-03-30 09:40:03 +00:00
|
|
|
HttpServer::new(move || {
|
2022-04-15 19:58:07 +00:00
|
|
|
let mut clients = ClientManager::open_or_create(config.clients_file())
|
2022-04-06 15:18:06 +00:00
|
|
|
.expect("Failed to load clients list!");
|
2022-04-15 19:58:07 +00:00
|
|
|
clients.apply_environment_variables();
|
2022-04-06 15:18:06 +00:00
|
|
|
|
2022-11-11 11:26:02 +00:00
|
|
|
let session_mw = SessionMiddleware::builder(
|
|
|
|
CookieSessionStore::default(),
|
|
|
|
Key::from(config.token_key.as_bytes()),
|
|
|
|
)
|
|
|
|
.cookie_name(SESSION_COOKIE_NAME.to_string())
|
|
|
|
.cookie_secure(config.secure_cookie())
|
|
|
|
.cookie_same_site(SameSite::Lax)
|
|
|
|
.build();
|
2022-07-22 10:21:38 +00:00
|
|
|
|
|
|
|
let identity_middleware = IdentityMiddleware::builder()
|
|
|
|
.logout_behaviour(LogoutBehaviour::PurgeSession)
|
|
|
|
.visit_deadline(Some(Duration::from_secs(MAX_INACTIVITY_DURATION)))
|
|
|
|
.login_deadline(Some(Duration::from_secs(MAX_SESSION_DURATION)))
|
|
|
|
.build();
|
2022-03-30 14:58:00 +00:00
|
|
|
|
2022-03-30 08:14:39 +00:00
|
|
|
App::new()
|
2022-03-30 09:40:03 +00:00
|
|
|
.app_data(web::Data::new(users_actor.clone()))
|
2022-04-03 14:45:25 +00:00
|
|
|
.app_data(web::Data::new(bruteforce_actor.clone()))
|
2022-04-09 10:18:59 +00:00
|
|
|
.app_data(web::Data::new(openid_sessions_actor.clone()))
|
2022-04-06 15:18:06 +00:00
|
|
|
.app_data(web::Data::new(clients))
|
2022-04-13 17:07:58 +00:00
|
|
|
.app_data(web::Data::new(jwt_signer.clone()))
|
2022-04-20 19:06:53 +00:00
|
|
|
.app_data(web::Data::new(webauthn_manager.clone()))
|
2022-11-11 11:26:02 +00:00
|
|
|
.wrap(
|
|
|
|
middleware::DefaultHeaders::new().add(("Permissions-Policy", "interest-cohort=()")),
|
|
|
|
)
|
2022-03-30 08:29:10 +00:00
|
|
|
.wrap(Logger::default())
|
2022-04-02 13:44:09 +00:00
|
|
|
.wrap(AuthMiddleware {})
|
2022-07-22 10:21:38 +00:00
|
|
|
.wrap(identity_middleware)
|
|
|
|
.wrap(session_mw)
|
2022-04-04 15:43:53 +00:00
|
|
|
// main route
|
2022-11-11 11:26:02 +00:00
|
|
|
.route(
|
|
|
|
"/",
|
|
|
|
web::get().to(|| async {
|
|
|
|
HttpResponse::Found()
|
|
|
|
.append_header(("Location", "/settings"))
|
|
|
|
.finish()
|
|
|
|
}),
|
|
|
|
)
|
2022-04-23 18:41:31 +00:00
|
|
|
.route("/robots.txt", web::get().to(assets_controller::robots_txt))
|
2022-04-04 15:39:23 +00:00
|
|
|
// health route
|
2022-03-30 08:14:39 +00:00
|
|
|
.service(health)
|
2022-03-30 09:40:03 +00:00
|
|
|
// Assets serving
|
2022-03-30 08:14:39 +00:00
|
|
|
.route("/assets/{path:.*}", web::get().to(assets_route))
|
2022-04-23 18:17:49 +00:00
|
|
|
// Login pages
|
|
|
|
.route("/logout", web::get().to(login_controller::logout_route))
|
2022-04-19 15:49:57 +00:00
|
|
|
.route("/login", web::get().to(login_controller::login_route))
|
|
|
|
.route("/login", web::post().to(login_controller::login_route))
|
2022-11-11 11:26:02 +00:00
|
|
|
.route(
|
|
|
|
"/reset_password",
|
|
|
|
web::get().to(login_controller::reset_password_route),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/reset_password",
|
|
|
|
web::post().to(login_controller::reset_password_route),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/2fa_auth",
|
|
|
|
web::get().to(login_controller::choose_2fa_method),
|
|
|
|
)
|
2022-04-19 17:24:07 +00:00
|
|
|
.route("/2fa_otp", web::get().to(login_controller::login_with_otp))
|
|
|
|
.route("/2fa_otp", web::post().to(login_controller::login_with_otp))
|
2022-11-11 11:26:02 +00:00
|
|
|
.route(
|
|
|
|
"/2fa_webauthn",
|
|
|
|
web::get().to(login_controller::login_with_webauthn),
|
|
|
|
)
|
2022-04-23 18:17:49 +00:00
|
|
|
// Login api
|
2022-11-11 11:26:02 +00:00
|
|
|
.route(
|
|
|
|
"/login/api/auth_webauthn",
|
|
|
|
web::post().to(login_api::auth_webauthn),
|
|
|
|
)
|
2022-04-04 15:39:23 +00:00
|
|
|
// Settings routes
|
2022-11-11 11:26:02 +00:00
|
|
|
.route(
|
|
|
|
"/settings",
|
|
|
|
web::get().to(settings_controller::account_settings_details_route),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/settings/change_password",
|
|
|
|
web::get().to(settings_controller::change_password_route),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/settings/change_password",
|
|
|
|
web::post().to(settings_controller::change_password_route),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/settings/two_factors",
|
|
|
|
web::get().to(two_factors_controller::two_factors_route),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/settings/two_factors/add_totp",
|
|
|
|
web::get().to(two_factors_controller::add_totp_factor_route),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/settings/two_factors/add_webauthn",
|
|
|
|
web::get().to(two_factors_controller::add_webauthn_factor_route),
|
|
|
|
)
|
2022-04-19 09:01:31 +00:00
|
|
|
// User API
|
2022-11-11 11:26:02 +00:00
|
|
|
.route(
|
|
|
|
"/settings/api/two_factor/save_totp_factor",
|
|
|
|
web::post().to(two_factor_api::save_totp_factor),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/settings/api/two_factor/save_webauthn_factor",
|
|
|
|
web::post().to(two_factor_api::save_webauthn_factor),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/settings/api/two_factor/delete_factor",
|
|
|
|
web::post().to(two_factor_api::delete_factor),
|
|
|
|
)
|
2022-11-12 10:50:32 +00:00
|
|
|
.route(
|
|
|
|
"/settings/api/two_factor/clear_login_history",
|
|
|
|
// Use POST to prevent CSRF
|
|
|
|
web::post().to(two_factor_api::clear_login_history),
|
|
|
|
)
|
2022-04-06 15:18:06 +00:00
|
|
|
// Admin routes
|
2022-11-11 11:26:02 +00:00
|
|
|
.route(
|
|
|
|
"/admin",
|
|
|
|
web::get().to(|| async {
|
|
|
|
HttpResponse::Found()
|
|
|
|
.append_header(("Location", "/settings"))
|
|
|
|
.finish()
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/admin/clients",
|
|
|
|
web::get().to(admin_controller::clients_route),
|
|
|
|
)
|
2022-04-06 16:03:00 +00:00
|
|
|
.route("/admin/users", web::get().to(admin_controller::users_route))
|
2022-11-11 11:26:02 +00:00
|
|
|
.route(
|
|
|
|
"/admin/users",
|
|
|
|
web::post().to(admin_controller::users_route),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/admin/create_user",
|
|
|
|
web::get().to(admin_controller::create_user),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/admin/edit_user",
|
|
|
|
web::get().to(admin_controller::edit_user),
|
|
|
|
)
|
2022-04-07 15:57:10 +00:00
|
|
|
// Admin API
|
2022-11-11 11:26:02 +00:00
|
|
|
.route(
|
|
|
|
"/admin/api/find_username",
|
|
|
|
web::post().to(admin_api::find_username),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
"/admin/api/delete_user",
|
|
|
|
web::post().to(admin_api::delete_user),
|
|
|
|
)
|
2022-04-09 09:30:23 +00:00
|
|
|
// OpenID routes
|
2022-11-11 11:26:02 +00:00
|
|
|
.route(
|
|
|
|
"/.well-known/openid-configuration",
|
|
|
|
web::get().to(openid_controller::get_configuration),
|
|
|
|
)
|
2022-04-12 18:40:44 +00:00
|
|
|
.route(AUTHORIZE_URI, web::get().to(openid_controller::authorize))
|
|
|
|
.route(TOKEN_URI, web::post().to(openid_controller::token))
|
2022-04-13 17:07:58 +00:00
|
|
|
.route(CERT_URI, web::get().to(openid_controller::cert_uri))
|
2022-11-11 11:26:02 +00:00
|
|
|
.route(
|
|
|
|
USERINFO_URI,
|
|
|
|
web::post().to(openid_controller::user_info_post),
|
|
|
|
)
|
|
|
|
.route(
|
|
|
|
USERINFO_URI,
|
|
|
|
web::get().to(openid_controller::user_info_get),
|
|
|
|
)
|
2022-03-30 08:14:39 +00:00
|
|
|
})
|
2022-11-11 11:26:02 +00:00
|
|
|
.bind(listen_address)?
|
|
|
|
.run()
|
|
|
|
.await
|
2022-03-30 06:42:18 +00:00
|
|
|
}
|