summaryrefslogtreecommitdiff
path: root/src/modules/auth/mod.rs
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-05-30 00:09:11 +0200
committermetamuffin <metamuffin@disroot.org>2024-05-30 00:09:11 +0200
commit532cc431d1c5ca1ffcf429a4ccb94edc7848fe7a (patch)
treec4422c4d54e01f63bae391cd95788cad74f59fbb /src/modules/auth/mod.rs
parent8b39940a58c28bc1bbe291eb5229e9ce1444e33c (diff)
downloadgnix-532cc431d1c5ca1ffcf429a4ccb94edc7848fe7a.tar
gnix-532cc431d1c5ca1ffcf429a4ccb94edc7848fe7a.tar.bz2
gnix-532cc431d1c5ca1ffcf429a4ccb94edc7848fe7a.tar.zst
rename filters dir
Diffstat (limited to 'src/modules/auth/mod.rs')
-rw-r--r--src/modules/auth/mod.rs90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/modules/auth/mod.rs b/src/modules/auth/mod.rs
new file mode 100644
index 0000000..d6e1a35
--- /dev/null
+++ b/src/modules/auth/mod.rs
@@ -0,0 +1,90 @@
+use argon2::PasswordVerifier;
+use argon2::{
+ password_hash::{Encoding, PasswordHashString},
+ Algorithm, Argon2, Params, PasswordHash, Version,
+};
+use serde::de::MapAccess;
+use serde::{
+ de::{value, Error, Visitor},
+ Deserialize,
+};
+use std::{collections::HashMap, fmt, fs::read_to_string};
+
+pub mod basic;
+pub mod cookie;
+
+struct Credentials {
+ wrong_user: PasswordHashString,
+ hashes: HashMap<String, PasswordHashString>,
+}
+
+impl Credentials {
+ fn get(&self, usernamme: &str) -> &PasswordHashString {
+ self.hashes.get(usernamme).unwrap_or(&self.wrong_user)
+ }
+ pub fn authentificate(&self, usernamme: &str, password: &str) -> bool {
+ let algo = Argon2::new(Algorithm::Argon2id, Version::V0x13, Params::default());
+ let hash = self.get(usernamme);
+ match hash.algorithm().as_str() {
+ "argon2id" => algo
+ .verify_password(
+ password.as_bytes(),
+ &PasswordHash::parse(hash.as_str(), hash.encoding()).unwrap(),
+ )
+ .is_ok(),
+ "never" => false,
+ _ => false,
+ }
+ }
+}
+
+impl<'de> Deserialize<'de> for Credentials {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ struct StringOrMap;
+ impl<'de> Visitor<'de> for StringOrMap {
+ type Value = HashMap<String, String>;
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("credentials map or file path")
+ }
+ fn visit_str<E>(self, val: &str) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ let path = String::deserialize(value::StrDeserializer::new(val))?;
+ let c = serde_yaml::from_str(&read_to_string(path).map_err(|io| {
+ serde::de::Error::custom(format!("cannot read creds file: {io:?}"))
+ })?)
+ .map_err(|e| serde::de::Error::custom(format!("cannot parse creds file: {e:?}")))?;
+ Ok(c)
+ }
+ fn visit_map<A>(self, val: A) -> Result<Self::Value, A::Error>
+ where
+ A: MapAccess<'de>,
+ {
+ Ok(HashMap::deserialize(value::MapAccessDeserializer::new(
+ val,
+ ))?)
+ }
+ }
+ let k = deserializer.deserialize_any(StringOrMap)?;
+ Ok(Credentials {
+ wrong_user: PasswordHashString::parse("$never", Encoding::B64).unwrap(),
+ hashes: k
+ .into_iter()
+ .map(|(k, v)| {
+ let hash = PasswordHash::parse(&v, Encoding::B64)
+ .map_err(|e| {
+ serde::de::Error::custom(format!(
+ "phc string for user {k:?} is invalid: {e:?}"
+ ))
+ })?
+ .serialize();
+ Ok((k, hash))
+ })
+ .try_collect()?,
+ })
+ }
+}