BasicOIDC/src/controllers/two_factors_controller.rs
Pierre Hubert bfe65b0216
All checks were successful
continuous-integration/drone/push Build is passing
Add IP location service
2022-11-12 17:02:34 +01:00

112 lines
3.2 KiB
Rust

use std::ops::Deref;
use actix_web::{HttpResponse, Responder};
use askama::Template;
use qrcode_generator::QrCodeEcc;
use crate::controllers::settings_controller::BaseSettingsPage;
use crate::data::app_config::AppConfig;
use crate::data::current_user::CurrentUser;
use crate::data::totp_key::TotpKey;
use crate::data::user::User;
use crate::data::webauthn_manager::WebAuthManagerReq;
#[derive(Template)]
#[template(path = "settings/two_factors_page.html")]
struct TwoFactorsPage<'a> {
_p: BaseSettingsPage,
user: &'a User,
}
#[derive(Template)]
#[template(path = "settings/add_2fa_totp_page.html")]
struct AddTotpPage {
_p: BaseSettingsPage,
qr_code: String,
account_name: String,
secret_key: String,
}
#[derive(Template)]
#[template(path = "settings/add_webauthn_page.html")]
struct AddWebauhtnPage {
_p: BaseSettingsPage,
opaque_state: String,
challenge_json: String,
}
/// Manage two factors authentication methods route
pub async fn two_factors_route(user: CurrentUser) -> impl Responder {
HttpResponse::Ok().body(
TwoFactorsPage {
_p: BaseSettingsPage::get("Two factor auth", &user, None, None),
user: user.deref(),
}
.render()
.unwrap(),
)
}
/// Configure a new TOTP authentication factor
pub async fn add_totp_factor_route(user: CurrentUser) -> impl Responder {
let key = TotpKey::new_random();
let qr_code = qrcode_generator::to_png_to_vec(
key.url_for_user(&user, AppConfig::get()),
QrCodeEcc::Low,
1024,
);
let qr_code = match qr_code {
Ok(q) => q,
Err(e) => {
log::error!("Failed to generate QrCode! {:?}", e);
return HttpResponse::InternalServerError().body("Failed to generate QrCode!");
}
};
HttpResponse::Ok().body(
AddTotpPage {
_p: BaseSettingsPage::get("New authenticator app", &user, None, None),
qr_code: base64::encode(qr_code),
account_name: key.account_name(&user, AppConfig::get()),
secret_key: key.get_secret(),
}
.render()
.unwrap(),
)
}
/// Configure a new security key factor
pub async fn add_webauthn_factor_route(
user: CurrentUser,
manager: WebAuthManagerReq,
) -> impl Responder {
let registration_request = match manager.start_register(&user) {
Ok(r) => r,
Err(e) => {
log::error!("Failed to request new key! {:?}", e);
return HttpResponse::InternalServerError()
.body("Failed to generate request for registration!");
}
};
let challenge_json = match serde_json::to_string(&registration_request.creation_challenge) {
Ok(r) => r,
Err(e) => {
log::error!("Failed to serialize challenge! {:?}", e);
return HttpResponse::InternalServerError().body("Failed to serialize challenge!");
}
};
HttpResponse::Ok().body(
AddWebauhtnPage {
_p: BaseSettingsPage::get("New security key", &user, None, None),
opaque_state: registration_request.opaque_state,
challenge_json: urlencoding::encode(&challenge_json).to_string(),
}
.render()
.unwrap(),
)
}