use crate::actors::users_actor; use crate::actors::users_actor::UsersActor; use crate::data::action_logger::{Action, ActionLogger}; use crate::data::remote_ip::RemoteIP; use actix::Addr; use actix_identity::Identity; use actix_web::{web, HttpRequest, HttpResponse, Responder}; use webauthn_rs::prelude::PublicKeyCredential; use crate::data::session_identity::{SessionIdentity, SessionStatus}; use crate::data::webauthn_manager::WebAuthManagerReq; #[derive(serde::Deserialize)] pub struct AuthWebauthnRequest { opaque_state: String, credential: PublicKeyCredential, } pub async fn auth_webauthn( id: Identity, req: web::Json, manager: WebAuthManagerReq, http_req: HttpRequest, remote_ip: RemoteIP, users: web::Data>, logger: ActionLogger, ) -> impl Responder { if !SessionIdentity(Some(&id)).need_2fa_auth() { return HttpResponse::Unauthorized().json("No 2FA required!"); } let user_id = SessionIdentity(Some(&id)).user_id(); match manager.finish_authentication(&user_id, &req.opaque_state, &req.credential) { Ok(_) => { users .send(users_actor::AddSuccessful2FALogin( user_id.clone(), remote_ip.0, )) .await .unwrap(); SessionIdentity(Some(&id)).set_status(&http_req, SessionStatus::SignedIn); logger.log(Action::LoginWebauthnAttempt { success: true, user_id, }); HttpResponse::Ok().body("You are authenticated!") } Err(e) => { log::error!("Failed to authenticate user using webauthn! {:?}", e); logger.log(Action::LoginWebauthnAttempt { success: false, user_id, }); HttpResponse::InternalServerError().body("Failed to validate security key!") } } }