Managed to authenticate user using Webauthn
This commit is contained in:
parent
05d3bee328
commit
9e345895ff
33
src/controllers/login_api.rs
Normal file
33
src/controllers/login_api.rs
Normal 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!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
pub mod assets_controller;
|
pub mod assets_controller;
|
||||||
pub mod base_controller;
|
pub mod base_controller;
|
||||||
pub mod login_controller;
|
pub mod login_controller;
|
||||||
|
pub mod login_api;
|
||||||
pub mod settings_controller;
|
pub mod settings_controller;
|
||||||
pub mod admin_controller;
|
pub mod admin_controller;
|
||||||
pub mod admin_api;
|
pub mod admin_api;
|
||||||
|
@ -3,7 +3,7 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use actix_web::web;
|
use actix_web::web;
|
||||||
use webauthn_rs::{AuthenticationState, RegistrationState, Webauthn, WebauthnConfig};
|
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::constants::APP_NAME;
|
||||||
use crate::data::app_config::AppConfig;
|
use crate::data::app_config::AppConfig;
|
||||||
@ -45,6 +45,7 @@ pub struct RegisterKeyRequest {
|
|||||||
struct RegisterKeyOpaqueData {
|
struct RegisterKeyOpaqueData {
|
||||||
registration_state: RegistrationState,
|
registration_state: RegistrationState,
|
||||||
user_id: UserID,
|
user_id: UserID,
|
||||||
|
// TODO : add time
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AuthRequest {
|
pub struct AuthRequest {
|
||||||
@ -56,6 +57,7 @@ pub struct AuthRequest {
|
|||||||
struct AuthStateOpaqueData {
|
struct AuthStateOpaqueData {
|
||||||
authentication_state: AuthenticationState,
|
authentication_state: AuthenticationState,
|
||||||
user_id: UserID,
|
user_id: UserID,
|
||||||
|
// TODO : add time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -123,4 +125,17 @@ impl WebAuthManager {
|
|||||||
login_challenge,
|
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(())
|
||||||
|
}
|
||||||
}
|
}
|
@ -111,7 +111,8 @@ async fn main() -> std::io::Result<()> {
|
|||||||
// Assets serving
|
// Assets serving
|
||||||
.route("/assets/{path:.*}", web::get().to(assets_route))
|
.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::get().to(login_controller::login_route))
|
||||||
.route("/login", web::post().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))
|
.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_otp", web::post().to(login_controller::login_with_otp))
|
||||||
.route("/2fa_webauthn", web::get().to(login_controller::login_with_webauthn))
|
.route("/2fa_webauthn", web::get().to(login_controller::login_with_webauthn))
|
||||||
|
|
||||||
// Logout page
|
// Login api
|
||||||
.route("/logout", web::get().to(login_controller::logout_route))
|
.route("/login/api/auth_webauthn", web::post().to(login_api::auth_webauthn))
|
||||||
|
|
||||||
// Settings routes
|
// Settings routes
|
||||||
.route("/settings", web::get().to(settings_controller::account_settings_details_route))
|
.route("/settings", web::get().to(settings_controller::account_settings_details_route))
|
||||||
|
Loading…
Reference in New Issue
Block a user