Managed to authenticate user using Webauthn

This commit is contained in:
Pierre HUBERT 2022-04-23 20:17:49 +02:00
parent 05d3bee328
commit 9e345895ff
4 changed files with 54 additions and 4 deletions

View File

@ -0,0 +1,33 @@
use actix_identity::Identity;
use actix_web::{HttpResponse, Responder, web};
use webauthn_rs::proto::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<AuthWebauthnRequest>,
manager: WebAuthManagerReq) -> impl Responder {
if !SessionIdentity(&id).need_2fa_auth() {
return HttpResponse::Unauthorized().json("No 2FA required!");
}
let user_id = SessionIdentity(&id).user_id();
match manager.finish_authentication(&user_id, &req.opaque_state, &req.credential) {
Ok(_) => {
SessionIdentity(&id).set_status(SessionStatus::SignedIn);
HttpResponse::Ok().body("You are authenticated!")
}
Err(e) => {
log::error!("Failed to authenticate user using webauthn! {:?}", e);
HttpResponse::InternalServerError().body("Failed to validate security key!")
}
}
}

View File

@ -1,6 +1,7 @@
pub mod assets_controller;
pub mod base_controller;
pub mod login_controller;
pub mod login_api;
pub mod settings_controller;
pub mod admin_controller;
pub mod admin_api;

View File

@ -3,7 +3,7 @@ use std::sync::Arc;
use actix_web::web;
use webauthn_rs::{AuthenticationState, RegistrationState, Webauthn, WebauthnConfig};
use webauthn_rs::proto::{CreationChallengeResponse, Credential, RegisterPublicKeyCredential, RequestChallengeResponse};
use webauthn_rs::proto::{CreationChallengeResponse, Credential, PublicKeyCredential, RegisterPublicKeyCredential, RequestChallengeResponse};
use crate::constants::APP_NAME;
use crate::data::app_config::AppConfig;
@ -45,6 +45,7 @@ pub struct RegisterKeyRequest {
struct RegisterKeyOpaqueData {
registration_state: RegistrationState,
user_id: UserID,
// TODO : add time
}
pub struct AuthRequest {
@ -56,6 +57,7 @@ pub struct AuthRequest {
struct AuthStateOpaqueData {
authentication_state: AuthenticationState,
user_id: UserID,
// TODO : add time
}
@ -123,4 +125,17 @@ impl WebAuthManager {
login_challenge,
})
}
pub fn finish_authentication(&self, user_id: &UserID, opaque_state: &str,
pub_cred: &PublicKeyCredential) -> Res {
let state: AuthStateOpaqueData = self.crypto_wrapper.decrypt(opaque_state)?;
if &state.user_id != user_id {
return Err(Box::new(
std::io::Error::new(ErrorKind::Other, "Invalid user for pubkey!")));
}
self.core.authenticate_credential(pub_cred, &state.authentication_state)?;
Ok(())
}
}

View File

@ -111,7 +111,8 @@ async fn main() -> std::io::Result<()> {
// Assets serving
.route("/assets/{path:.*}", web::get().to(assets_route))
// Login page
// Login pages
.route("/logout", web::get().to(login_controller::logout_route))
.route("/login", web::get().to(login_controller::login_route))
.route("/login", web::post().to(login_controller::login_route))
.route("/reset_password", web::get().to(login_controller::reset_password_route))
@ -121,8 +122,8 @@ async fn main() -> std::io::Result<()> {
.route("/2fa_otp", web::post().to(login_controller::login_with_otp))
.route("/2fa_webauthn", web::get().to(login_controller::login_with_webauthn))
// Logout page
.route("/logout", web::get().to(login_controller::logout_route))
// Login api
.route("/login/api/auth_webauthn", web::post().to(login_api::auth_webauthn))
// Settings routes
.route("/settings", web::get().to(settings_controller::account_settings_details_route))