Compare commits
6 Commits
231ce8f9cf
...
20260223
| Author | SHA1 | Date | |
|---|---|---|---|
| cc72ff64d2 | |||
| 3482c53acf | |||
| 84c3415ad7 | |||
| cc2c3d7626 | |||
| 965a7dbe8b | |||
| bc6bdcbc7d |
691
Cargo.lock
generated
691
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
23
Cargo.toml
23
Cargo.toml
@@ -8,38 +8,35 @@ edition = "2024"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
actix = "0.13.5"
|
actix = "0.13.5"
|
||||||
actix-identity = "0.9.0"
|
actix-identity = "0.9.0"
|
||||||
actix-web = "4.12.1"
|
actix-web = "4.13.0"
|
||||||
actix-session = { version = "0.11.0", features = ["cookie-session", "redis-session"] }
|
actix-session = { version = "0.11.0", features = ["cookie-session", "redis-session"] }
|
||||||
actix-remote-ip = "0.1.0"
|
actix-remote-ip = "0.1.0"
|
||||||
clap = { version = "4.5.58", features = ["derive", "env"] }
|
clap = { version = "4.5.60", features = ["derive", "env"] }
|
||||||
include_dir = "0.7.4"
|
include_dir = "0.7.4"
|
||||||
log = "0.4.29"
|
log = "0.4.29"
|
||||||
serde_json = "1.0.149"
|
serde_json = "1.0.149"
|
||||||
serde_yaml = "0.9.34"
|
serde_yml = "0.0.12"
|
||||||
env_logger = "0.11.8"
|
env_logger = "0.11.9"
|
||||||
serde = { version = "1.0.228", features = ["derive"] }
|
serde = { version = "1.0.228", features = ["derive"] }
|
||||||
bcrypt = "0.18.0"
|
bcrypt = "0.18.0"
|
||||||
uuid = { version = "1.20.0", features = ["v4"] }
|
uuid = { version = "1.21.0", features = ["v4"] }
|
||||||
mime_guess = "2.0.5"
|
mime_guess = "2.0.5"
|
||||||
askama = "0.15.4"
|
askama = "0.15.4"
|
||||||
urlencoding = "2.1.3"
|
urlencoding = "2.1.3"
|
||||||
rand = "0.9.0"
|
rand = "0.10.0"
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
jwt-simple = { version = "0.12.14", default-features = false, features = ["pure-rust"] }
|
jwt-simple = { version = "0.12.14", default-features = false, features = ["pure-rust"] }
|
||||||
digest = "0.11.0"
|
sha2 = "0.11.0-rc.5"
|
||||||
sha2 = "0.11.0-rc.4"
|
lazy-regex = "3.6.0"
|
||||||
lazy-regex = "3.5.1"
|
|
||||||
totp_rfc6238 = "0.6.1"
|
totp_rfc6238 = "0.6.1"
|
||||||
base32 = "0.5.1"
|
base32 = "0.5.1"
|
||||||
qrcode-generator = "5.0.0"
|
qrcode-generator = "5.0.0"
|
||||||
webauthn-rs = { version = "0.5.4", features = ["danger-allow-state-serialisation"] }
|
webauthn-rs = { version = "0.5.4", features = ["danger-allow-state-serialisation"] }
|
||||||
url = "2.5.8"
|
url = "2.5.8"
|
||||||
light-openid = { version = "1.1.0", features = ["crypto-wrapper"] }
|
light-openid = { version = "1.1.0", features = ["crypto-wrapper"] }
|
||||||
rkyv = "0.8.14"
|
rkyv = "0.8.15"
|
||||||
chrono = "0.4.43"
|
chrono = "0.4.43"
|
||||||
lazy_static = "1.5.0"
|
|
||||||
mailchecker = "6.0.19"
|
mailchecker = "6.0.19"
|
||||||
httpdate = "1.0.3"
|
httpdate = "1.0.3"
|
||||||
build-time = "0.1.3"
|
build-time = "0.1.3"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
anyhow = "1.0.101"
|
|
||||||
@@ -17,17 +17,20 @@ pub struct SessionID(pub String);
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
pub session_id: SessionID,
|
|
||||||
pub client: ClientID,
|
pub client: ClientID,
|
||||||
pub user: UserID,
|
pub user: UserID,
|
||||||
pub auth_time: u64,
|
pub auth_time: u64,
|
||||||
pub redirect_uri: String,
|
pub redirect_uri: String,
|
||||||
|
|
||||||
|
pub session_id: SessionID,
|
||||||
|
pub session_expire_at: u64,
|
||||||
|
|
||||||
pub authorization_code: String,
|
pub authorization_code: String,
|
||||||
pub authorization_code_expire_at: u64,
|
pub authorization_code_expire_at: u64,
|
||||||
|
|
||||||
pub access_token: Option<String>,
|
pub access_token: Option<String>,
|
||||||
pub access_token_expire_at: u64,
|
pub access_token_expire_at: u64,
|
||||||
|
|
||||||
pub refresh_token: String,
|
pub refresh_token: String,
|
||||||
pub refresh_token_expire_at: u64,
|
pub refresh_token_expire_at: u64,
|
||||||
|
|
||||||
@@ -37,9 +40,10 @@ pub struct Session {
|
|||||||
|
|
||||||
impl Session {
|
impl Session {
|
||||||
pub fn is_expired(&self) -> bool {
|
pub fn is_expired(&self) -> bool {
|
||||||
self.authorization_code_expire_at < time()
|
self.session_expire_at < time()
|
||||||
&& self.access_token_expire_at < time()
|
|| (self.authorization_code_expire_at < time()
|
||||||
&& self.refresh_token_expire_at < time()
|
&& self.access_token_expire_at < time()
|
||||||
|
&& self.refresh_token_expire_at < time())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn regenerate_access_and_refresh_tokens(
|
pub fn regenerate_access_and_refresh_tokens(
|
||||||
|
|||||||
@@ -64,7 +64,8 @@ pub const USERINFO_URI: &str = "/openid/userinfo";
|
|||||||
|
|
||||||
/// Open ID constants
|
/// Open ID constants
|
||||||
pub const OPEN_ID_SESSION_CLEANUP_INTERVAL: Duration = Duration::from_secs(60);
|
pub const OPEN_ID_SESSION_CLEANUP_INTERVAL: Duration = Duration::from_secs(60);
|
||||||
pub const OPEN_ID_SESSION_LEN: usize = 40;
|
pub const OPEN_ID_SESSION_ID_LEN: usize = 40;
|
||||||
|
pub const OPEN_ID_SESSION_MAX_DURATION: Duration = Duration::from_secs(3600 * 24 * 7);
|
||||||
pub const OPEN_ID_AUTHORIZATION_CODE_LEN: usize = 120;
|
pub const OPEN_ID_AUTHORIZATION_CODE_LEN: usize = 120;
|
||||||
pub const OPEN_ID_AUTHORIZATION_CODE_TIMEOUT: u64 = 300;
|
pub const OPEN_ID_AUTHORIZATION_CODE_TIMEOUT: u64 = 300;
|
||||||
pub const OPEN_ID_ACCESS_TOKEN_LEN: usize = 50;
|
pub const OPEN_ID_ACCESS_TOKEN_LEN: usize = 50;
|
||||||
|
|||||||
@@ -219,11 +219,12 @@ pub async fn authorize(
|
|||||||
(_, "code") => {
|
(_, "code") => {
|
||||||
// Save all authentication information in memory
|
// Save all authentication information in memory
|
||||||
let session = Session {
|
let session = Session {
|
||||||
session_id: SessionID(rand_str(OPEN_ID_SESSION_LEN)),
|
|
||||||
client: client.id.clone(),
|
client: client.id.clone(),
|
||||||
user: user.uid.clone(),
|
user: user.uid.clone(),
|
||||||
auth_time: SessionIdentity(Some(&id)).auth_time(),
|
auth_time: SessionIdentity(Some(&id)).auth_time(),
|
||||||
redirect_uri,
|
redirect_uri,
|
||||||
|
session_id: SessionID(rand_str(OPEN_ID_SESSION_ID_LEN)),
|
||||||
|
session_expire_at: time() + OPEN_ID_SESSION_MAX_DURATION.as_secs(),
|
||||||
authorization_code: rand_str(OPEN_ID_AUTHORIZATION_CODE_LEN),
|
authorization_code: rand_str(OPEN_ID_AUTHORIZATION_CODE_LEN),
|
||||||
authorization_code_expire_at: time() + OPEN_ID_AUTHORIZATION_CODE_TIMEOUT,
|
authorization_code_expire_at: time() + OPEN_ID_AUTHORIZATION_CODE_TIMEOUT,
|
||||||
access_token: None,
|
access_token: None,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::path::{Path, PathBuf};
|
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
use crate::constants::{
|
use crate::constants::{
|
||||||
APP_NAME, CLIENTS_LIST_FILE, OIDC_PROVIDER_CB_URI, PROVIDERS_LIST_FILE, USERS_LIST_FILE,
|
APP_NAME, CLIENTS_LIST_FILE, OIDC_PROVIDER_CB_URI, PROVIDERS_LIST_FILE, USERS_LIST_FILE,
|
||||||
@@ -93,23 +93,21 @@ pub struct AppConfig {
|
|||||||
redis_password: String,
|
redis_password: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
static ARGS: OnceLock<AppConfig> = OnceLock::new();
|
||||||
static ref ARGS: AppConfig = {
|
|
||||||
let mut config = AppConfig::parse();
|
|
||||||
|
|
||||||
// In debug mode only, use dummy token
|
|
||||||
if cfg!(debug_assertions) && config.token_key.is_empty() {
|
|
||||||
config.token_key = String::from_utf8_lossy(&[32; 64]).to_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
config
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AppConfig {
|
impl AppConfig {
|
||||||
/// Get parsed command line arguments
|
/// Get parsed command line arguments
|
||||||
pub fn get() -> &'static AppConfig {
|
pub fn get() -> &'static AppConfig {
|
||||||
&ARGS
|
ARGS.get_or_init(|| {
|
||||||
|
let mut config = AppConfig::parse();
|
||||||
|
|
||||||
|
// In debug mode only, use dummy token
|
||||||
|
if cfg!(debug_assertions) && config.token_key.is_empty() {
|
||||||
|
config.token_key = String::from_utf8_lossy(&[32; 64]).to_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
config
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn secure_cookie(&self) -> bool {
|
pub fn secure_cookie(&self) -> bool {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ where
|
|||||||
file_path: path.as_ref().to_path_buf(),
|
file_path: path.as_ref().to_path_buf(),
|
||||||
list: match Self::file_format(path.as_ref()) {
|
list: match Self::file_format(path.as_ref()) {
|
||||||
FileFormat::Json => serde_json::from_str(&file_content)?,
|
FileFormat::Json => serde_json::from_str(&file_content)?,
|
||||||
FileFormat::Yaml => serde_yaml::from_str(&file_content)?,
|
FileFormat::Yaml => serde_yml::from_str(&file_content)?,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ where
|
|||||||
&self.file_path,
|
&self.file_path,
|
||||||
match Self::file_format(self.file_path.as_ref()) {
|
match Self::file_format(self.file_path.as_ref()) {
|
||||||
FileFormat::Json => serde_json::to_string(&self.list)?,
|
FileFormat::Json => serde_json::to_string(&self.list)?,
|
||||||
FileFormat::Yaml => serde_yaml::to_string(&self.list)?,
|
FileFormat::Yaml => serde_yml::to_string(&self.list)?,
|
||||||
},
|
},
|
||||||
)?)
|
)?)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use base32::Alphabet;
|
use base32::Alphabet;
|
||||||
use rand::Rng;
|
use rand::RngExt;
|
||||||
use totp_rfc6238::{HashAlgorithm, TotpGenerator};
|
use totp_rfc6238::{HashAlgorithm, TotpGenerator};
|
||||||
|
|
||||||
use crate::data::app_config::AppConfig;
|
use crate::data::app_config::AppConfig;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use digest::Digest;
|
use sha2::Digest;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn sha256(input: &[u8]) -> Vec<u8> {
|
pub fn sha256(input: &[u8]) -> Vec<u8> {
|
||||||
|
|||||||
Reference in New Issue
Block a user