1
0
mirror of https://gitlab.com/comunic/comunicapiv3 synced 2024-11-25 23:09:22 +00:00

Update webauthn-rs crate

This commit is contained in:
Pierre HUBERT 2022-08-24 20:08:29 +02:00
parent 364bca03a6
commit bea1c56e44
11 changed files with 245 additions and 63 deletions

204
Cargo.lock generated
View File

@ -391,6 +391,45 @@ version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
[[package]]
name = "asn1-rs"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ff05a702273012438132f449575dbc804e27b2f3cbe3069aa237d26c98fa33"
dependencies = [
"asn1-rs-derive",
"asn1-rs-impl",
"displaydoc",
"nom",
"num-traits",
"rusticata-macros",
"thiserror",
"time 0.3.13",
]
[[package]]
name = "asn1-rs-derive"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db8b7511298d5b7784b40b092d9e9dcd3a627a5707e4b5e507931ab0d44eeebf"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "asn1-rs-impl"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "async-recursion"
version = "1.0.0"
@ -456,6 +495,17 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b"
[[package]]
name = "base64urlsafedata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d02340c3f25c8422ba85d481123406dd7506505485bac1c694b26eb538da8daf"
dependencies = [
"base64 0.13.0",
"serde",
"serde_json",
]
[[package]]
name = "bcrypt"
version = "0.13.0"
@ -740,6 +790,22 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "compact_jwt"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9417bb4f581b7a5e08fabb4398b910064363bbfd7b75a10d1da3bfff3ef9b36"
dependencies = [
"base64 0.13.0",
"base64urlsafedata",
"openssl",
"serde",
"serde_json",
"tracing",
"url",
"uuid 1.1.2",
]
[[package]]
name = "comunic_server"
version = "0.1.0"
@ -961,6 +1027,12 @@ dependencies = [
"parking_lot_core",
]
[[package]]
name = "data-encoding"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57"
[[package]]
name = "deflate"
version = "0.9.1"
@ -979,6 +1051,20 @@ dependencies = [
"adler32",
]
[[package]]
name = "der-parser"
version = "7.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe398ac75057914d7d07307bf67dc7f3f574a26783b4fc7805a20ffa9f506e82"
dependencies = [
"asn1-rs",
"displaydoc",
"nom",
"num-bigint 0.4.3",
"num-traits",
"rusticata-macros",
]
[[package]]
name = "derive_more"
version = "0.99.17"
@ -1023,6 +1109,17 @@ dependencies = [
"subtle",
]
[[package]]
name = "displaydoc"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "doc-comment"
version = "0.3.3"
@ -1911,9 +2008,9 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
[[package]]
name = "mailchecker"
version = "4.1.19"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfdf79ae4aa0804bf975b72d7e8330a810739ae8f717c55e747de1f09c6f9ae8"
checksum = "9188ee74b3b27e3a35bdc2764e806445de607a0d0324b0281bd0e5c5b8bad4a3"
dependencies = [
"fast_chemail",
"once_cell",
@ -2101,7 +2198,7 @@ dependencies = [
"subprocess",
"thiserror",
"time 0.3.13",
"uuid",
"uuid 0.8.2",
]
[[package]]
@ -2229,6 +2326,15 @@ dependencies = [
"libc",
]
[[package]]
name = "oid-registry"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38e20717fa0541f39bd146692035c37bedfa532b3e5071b35761082407546b2a"
dependencies = [
"asn1-rs",
]
[[package]]
name = "once_cell"
version = "1.13.1"
@ -2782,6 +2888,15 @@ dependencies = [
"semver",
]
[[package]]
name = "rusticata-macros"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
dependencies = [
"nom",
]
[[package]]
name = "rustls"
version = "0.18.1"
@ -3141,6 +3256,18 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "synstructure"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2",
"quote",
"syn",
"unicode-xid",
]
[[package]]
name = "tap"
version = "1.0.1"
@ -3408,6 +3535,12 @@ dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-xid"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
[[package]]
name = "untrusted"
version = "0.7.1"
@ -3439,6 +3572,16 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
[[package]]
name = "uuid"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f"
dependencies = [
"getrandom 0.2.7",
"serde",
]
[[package]]
name = "vcpkg"
version = "0.2.15"
@ -3557,21 +3700,52 @@ dependencies = [
[[package]]
name = "webauthn-rs"
version = "0.3.2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90b266eccb4b32595876f5c73ea443b0516da0b1df72ca07bc08ed9ba7f96ec1"
checksum = "08ea37595bdb8d731f39949249e41fb4c66cdad5487693575cc1078c8a67abac"
dependencies = [
"base64urlsafedata",
"serde",
"tracing",
"url",
"uuid 1.1.2",
"webauthn-rs-core",
]
[[package]]
name = "webauthn-rs-core"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15a12633855c4094f700cad8e2aad4c7d07d762745c4e26a1684a4351bcdf0d4"
dependencies = [
"base64 0.13.0",
"base64urlsafedata",
"compact_jwt",
"der-parser",
"nom",
"openssl",
"rand 0.8.5",
"serde",
"serde_cbor",
"serde_derive",
"serde_json",
"thiserror",
"tracing",
"url",
"uuid 1.1.2",
"webauthn-rs-proto",
"x509-parser",
]
[[package]]
name = "webauthn-rs-proto"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a72f222f4496b34acfc7809ac8440984665105785f3556b541ab14c515cf357"
dependencies = [
"base64urlsafedata",
"serde",
"serde_json",
"url",
]
[[package]]
@ -3710,6 +3884,24 @@ dependencies = [
"tap",
]
[[package]]
name = "x509-parser"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb9bace5b5589ffead1afb76e43e34cff39cd0f3ce7e170ae0c29e53b88eb1c"
dependencies = [
"asn1-rs",
"base64 0.13.0",
"data-encoding",
"der-parser",
"lazy_static",
"nom",
"oid-registry",
"rusticata-macros",
"thiserror",
"time 0.3.13",
]
[[package]]
name = "xml5ever"
version = "0.16.2"

View File

@ -20,7 +20,7 @@ serde_json = "1.0.82"
futures = "0.3.21"
encoding_rs = "0.8.31"
percent-encoding = "2.1.0"
mailchecker = "4.1.19"
mailchecker = "5.0.0"
sha1 = "0.10.1"
rand = "0.8.5"
chrono = "0.4.19"
@ -40,7 +40,7 @@ mp4 = "0.12.0"
zip = "0.6.2"
webpage = "1.4.0"
gouth = "0.2.1"
webauthn-rs = "0.3.2"
webauthn-rs = "0.4.3"
url = "2.2.2"
async-recursion = "1.0.0"
tokio = { version = "1.20.1", features = ["rt-multi-thread"] }

View File

@ -20,7 +20,7 @@ pub struct AdminAuthOptions {
}
impl AdminAuthOptions {
pub fn new(admin: &Admin, keys: &Vec<AdminKey>) -> Self {
pub fn new(admin: &Admin, keys: &[AdminKey]) -> Self {
Self {
reset_token: admin.reset_token.is_some(),
keys: keys.iter().map(|k| AuthKey { id: k.id, name: k.name.to_string(), password: k.password.is_some() }).collect(),

View File

@ -4,6 +4,7 @@
use bcrypt::verify;
use webauthn_rs::prelude::Uuid;
use crate::api_data::admin::admin_auth_success::AdminAuthSuccess;
use crate::api_data::admin::admin_keys_api::AdminKeyAPI;
@ -27,8 +28,7 @@ impl HttpRequestHandler {
let keys = admin_account_key_helper::get_admin_keys(admin.id)?;
let key = keys.into_iter()
.filter(|k| k.id == key_id)
.next();
.find(|k| k.id == key_id);
match key {
Some(key) => Ok(key),
@ -55,7 +55,13 @@ pub async fn get_keys_list(r: &mut HttpRequestHandler) -> RequestResult {
pub async fn challenge_register_key(r: &mut HttpRequestHandler) -> RequestResult {
let wan = get_wan();
let (res, state) = wan.generate_challenge_register(&r.admin_id()?.id_str(), false)?;
let user_info = admin_account_helper::find_admin_by_id(r.admin_id()?)?;
let (res, state) = wan.start_passkey_registration(
Uuid::new_v4(),
&user_info.name,
&user_info.name,
None)?;
admin_key_registration_challenges_helper::set(r.admin_id()?, state)?;
@ -74,9 +80,9 @@ pub async fn register_key(r: &mut HttpRequestHandler) -> RequestResult {
)?;
let wan = get_wan();
let key = wan.register_credential(&creds, &state, |_| Ok(false))?;
let key = wan.finish_passkey_registration(&creds, &state)?;
let key_id = admin_account_key_helper::add_key(r.admin_id()?, &key_name, key.0, key_password)?;
let key_id = admin_account_key_helper::add_key(r.admin_id()?, &key_name, key, key_password)?;
log_admin_action(r.admin_id()?, &r.remote_ip(),
AdminAction::RegisteredAdminKey {
@ -120,7 +126,7 @@ pub async fn challenge_auth_with_key(r: &mut HttpRequestHandler) -> RequestResul
let key = r.post_admin_auth_key("mail", "key_id")?;
let (challenge_response, auth_state) =
get_wan().generate_challenge_authenticate(vec![key.key])?;
get_wan().start_passkey_authentication(&[key.key])?;
admin_key_authentication_challenges_helper::set(key.id, auth_state)?;
@ -138,9 +144,9 @@ pub async fn auth_with_key(r: &mut HttpRequestHandler) -> RequestResult {
)?;
// Perform authentication
let state = get_wan().authenticate_credential(&credentials, &state)?;
if !state.1.user_present {
r.forbidden("Invalid key!".to_string())?;
let state = get_wan().finish_passkey_authentication(&credentials, &state)?;
if !state.user_verified() {
r.forbidden("Invalid key! (user_verified = false)".to_string())?;
}
// Check key password (if any)

View File

@ -4,7 +4,7 @@
use mysql::serde::{Deserializer, Serializer};
use serde::{Deserialize, Serialize};
use webauthn_rs::proto::Credential;
use webauthn_rs::prelude::Passkey;
use crate::constants::admin::{ADMIN_ROLES_LIST, AdminRole};
use crate::data::u64_visitor::U64Visitor;
@ -50,7 +50,7 @@ pub struct AdminKey {
pub admin_id: AdminID,
pub name: String,
pub time_add: u64,
pub key: Credential,
pub key: Passkey,
pub password: Option<String>,
}
@ -98,6 +98,6 @@ impl Serialize for AdminID {
impl<'de> Deserialize<'de> for AdminID {
fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error> where
D: Deserializer<'de> {
deserializer.deserialize_u64(U64Visitor {}).map(|id| AdminID::new(id))
deserializer.deserialize_u64(U64Visitor {}).map(AdminID::new)
}
}

View File

@ -565,14 +565,14 @@ pub trait BaseRequestHandler {
}
/// Get the response to a key register credential included in the request
fn post_register_public_key_credential(&mut self, name: &str) -> Res<webauthn_rs::proto::RegisterPublicKeyCredential> {
fn post_register_public_key_credential(&mut self, name: &str) -> Res<webauthn_rs::prelude::RegisterPublicKeyCredential> {
let str = self.post_string(name)?;
Ok(serde_json::from_str(&str)?)
}
/// Get the response to a key authentication included in the request
fn post_auth_public_key_credential(&mut self, name: &str) -> Res<webauthn_rs::proto::PublicKeyCredential> {
fn post_auth_public_key_credential(&mut self, name: &str) -> Res<webauthn_rs::prelude::PublicKeyCredential> {
let str = self.post_string(name)?;
Ok(serde_json::from_str(&str)?)

View File

@ -2,41 +2,25 @@
//!
//! @author Pierre Hubert
use webauthn_rs::{Webauthn, WebauthnConfig};
use webauthn_rs::{Webauthn, WebauthnBuilder};
use crate::data::config::conf;
pub struct ComunicAdminWebauthnConfig {
origin: url::Url,
relying_party_id: String,
}
impl WebauthnConfig for ComunicAdminWebauthnConfig {
fn get_relying_party_name(&self) -> &str {
"ComunicAdmin"
}
fn get_origin(&self) -> &url::Url {
&self.origin
}
fn get_relying_party_id(&self) -> &str {
&self.relying_party_id
}
}
pub fn get_wan() -> Webauthn<ComunicAdminWebauthnConfig> {
Webauthn::new(ComunicAdminWebauthnConfig {
origin: url::Url::parse(&conf().admin_url).unwrap(),
relying_party_id: conf().admin_url
pub fn get_wan() -> Webauthn {
WebauthnBuilder::new(
conf().admin_url
.replace("https://", "")
.replace("http://", "")
.split(":")
.split(':')
.next()
.unwrap()
.split("/")
.split('/')
.next()
.unwrap()
.to_string(),
})
.unwrap(),
&url::Url::parse(&conf().admin_url).unwrap(),
)
.expect("Invalid Webauthn configuration!")
.rp_name("ComunicAdmin")
.build()
.expect("Failed to build Webauthn object")
}

View File

@ -21,7 +21,7 @@ pub fn create(new_admin: &NewAdmin) -> Res<AdminID> {
.add_str("name", &new_admin.name)
.add_str("email", &new_admin.email)
.insert_expect_result()
.map(|i| AdminID::new(i))
.map(AdminID::new)
}
/// Check out whether an admin exists or not

View File

@ -3,7 +3,7 @@
//! @author Pierre Hubert
use bcrypt::{DEFAULT_COST, hash_with_result};
use webauthn_rs::proto::Credential;
use webauthn_rs::prelude::Passkey;
use crate::constants::database_tables_names::ADMIN_KEYS_TABLE;
use crate::data::admin::{AdminID, AdminKey};
@ -12,7 +12,7 @@ use crate::helpers::database;
use crate::utils::date_utils::time;
/// Save a new key in the database
pub fn add_key(id: AdminID, name: &str, key: Credential, password: String) -> Res<u64> {
pub fn add_key(id: AdminID, name: &str, key: Passkey, password: String) -> Res<u64> {
database::InsertQuery::new(ADMIN_KEYS_TABLE)
.add_admin_id("admin_id", id)
.add_str("name", name)

View File

@ -7,11 +7,11 @@
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use webauthn_rs::AuthenticationState;
use webauthn_rs::prelude::PasskeyAuthentication;
use crate::data::error::Res;
static mut CACHE: Option<Arc<Mutex<HashMap<u64, AuthenticationState>>>> = None;
static mut CACHE: Option<Arc<Mutex<HashMap<u64, PasskeyAuthentication>>>> = None;
/// Initialize this helper's cache
pub fn init() {
@ -22,7 +22,7 @@ pub fn init() {
}
/// Store a new entry in the cache
pub fn set(key_id: u64, state: AuthenticationState) -> Res {
pub fn set(key_id: u64, state: PasskeyAuthentication) -> Res {
let cache = unsafe {
CACHE.as_ref().unwrap().lock()
};
@ -32,7 +32,7 @@ pub fn set(key_id: u64, state: AuthenticationState) -> Res {
Ok(())
}
pub fn get(key_id: u64) -> Res<Option<AuthenticationState>> {
pub fn get(key_id: u64) -> Res<Option<PasskeyAuthentication>> {
let cache = unsafe {
CACHE.as_ref().unwrap().lock()
};

View File

@ -7,12 +7,12 @@
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use webauthn_rs::RegistrationState;
use webauthn_rs::prelude::PasskeyRegistration;
use crate::data::admin::AdminID;
use crate::data::error::Res;
static mut CACHE: Option<Arc<Mutex<HashMap<AdminID, RegistrationState>>>> = None;
static mut CACHE: Option<Arc<Mutex<HashMap<AdminID, PasskeyRegistration>>>> = None;
/// Initialize this helper's cache
pub fn init() {
@ -23,7 +23,7 @@ pub fn init() {
}
/// Store a new entry in the cache
pub fn set(admin: AdminID, key: RegistrationState) -> Res {
pub fn set(admin: AdminID, key: PasskeyRegistration) -> Res {
let cache = unsafe {
CACHE.as_ref().unwrap().lock()
};
@ -33,7 +33,7 @@ pub fn set(admin: AdminID, key: RegistrationState) -> Res {
Ok(())
}
pub fn get(admin: AdminID) -> Res<Option<RegistrationState>> {
pub fn get(admin: AdminID) -> Res<Option<PasskeyRegistration>> {
let cache = unsafe {
CACHE.as_ref().unwrap().lock()
};