Add redis session store

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2025-06-04 23:43:41 +01:00
parent ec7055d5ff
commit 455bf7b88d
8 changed files with 507 additions and 85 deletions

411
Cargo.lock generated
View File

@@ -118,13 +118,105 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "async-channel"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35"
dependencies = [
"concurrent-queue",
"event-listener 2.5.3",
"futures-core",
]
[[package]]
name = "async-channel"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
dependencies = [
"concurrent-queue",
"event-listener-strategy",
"futures-core",
"pin-project-lite",
]
[[package]]
name = "async-executor"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa"
dependencies = [
"async-task",
"concurrent-queue",
"fastrand",
"futures-lite",
"pin-project-lite",
"slab",
]
[[package]]
name = "async-global-executor"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c"
dependencies = [
"async-channel 2.3.1",
"async-executor",
"async-io",
"async-lock 3.4.0",
"blocking",
"futures-lite",
"once_cell",
]
[[package]]
name = "async-io"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3"
dependencies = [
"async-lock 3.4.0",
"cfg-if 1.0.0",
"concurrent-queue",
"futures-io",
"futures-lite",
"parking",
"polling",
"rustix",
"slab",
"tracing",
"windows-sys 0.59.0",
]
[[package]]
name = "async-lock"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
dependencies = [
"event-listener",
"event-listener 2.5.3",
]
[[package]]
name = "async-lock"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
dependencies = [
"event-listener 5.4.0",
"event-listener-strategy",
"pin-project-lite",
]
[[package]]
name = "async-redis-session"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba82ce101e6cde598074604ef4a882bdd6b3a283baff446ae73ae2727c242452"
dependencies = [
"async-session",
"redis 0.20.2",
]
[[package]]
@@ -134,7 +226,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07da4ce523b4e2ebaaf330746761df23a465b951a83d84bbce4233dabedae630"
dependencies = [
"anyhow",
"async-lock",
"async-lock 2.8.0",
"async-trait",
"base64 0.13.1",
"bincode",
@@ -148,6 +240,38 @@ dependencies = [
"sha2 0.9.9",
]
[[package]]
name = "async-std"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "730294c1c08c2e0f85759590518f6333f0d5a0a766a27d519c1b244c3dfd8a24"
dependencies = [
"async-channel 1.9.0",
"async-global-executor",
"async-io",
"async-lock 3.4.0",
"crossbeam-utils",
"futures-channel",
"futures-core",
"futures-io",
"futures-lite",
"gloo-timers",
"kv-log-macro",
"log",
"memchr",
"once_cell",
"pin-project-lite",
"pin-utils",
"slab",
"wasm-bindgen-futures",
]
[[package]]
name = "async-task"
version = "4.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
[[package]]
name = "async-trait"
version = "0.1.88"
@@ -159,6 +283,12 @@ dependencies = [
"syn 2.0.101",
]
[[package]]
name = "atomic-waker"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]]
name = "autocfg"
version = "1.4.0"
@@ -181,7 +311,7 @@ dependencies = [
"http-body-util",
"hyper",
"hyper-util",
"itoa",
"itoa 1.0.15",
"matchit",
"memchr",
"mime",
@@ -356,6 +486,19 @@ dependencies = [
"generic-array",
]
[[package]]
name = "blocking"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea"
dependencies = [
"async-channel 2.3.1",
"async-task",
"futures-io",
"futures-lite",
"piper",
]
[[package]]
name = "bumpalo"
version = "3.17.0"
@@ -473,7 +616,16 @@ dependencies = [
"memchr",
"pin-project-lite",
"tokio",
"tokio-util",
"tokio-util 0.7.15",
]
[[package]]
name = "concurrent-queue"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
dependencies = [
"crossbeam-utils",
]
[[package]]
@@ -503,6 +655,12 @@ dependencies = [
"libc",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crypto-bigint"
version = "0.5.5"
@@ -688,6 +846,12 @@ dependencies = [
"syn 2.0.101",
]
[[package]]
name = "dtoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
[[package]]
name = "dyn-clone"
version = "1.0.19"
@@ -765,12 +929,49 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
dependencies = [
"libc",
"windows-sys 0.59.0",
]
[[package]]
name = "event-listener"
version = "2.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
[[package]]
name = "event-listener"
version = "5.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae"
dependencies = [
"concurrent-queue",
"parking",
"pin-project-lite",
]
[[package]]
name = "event-listener-strategy"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
dependencies = [
"event-listener 5.4.0",
"pin-project-lite",
]
[[package]]
name = "fastrand"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "ff"
version = "0.13.1"
@@ -817,6 +1018,25 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-io"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
[[package]]
name = "futures-lite"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532"
dependencies = [
"fastrand",
"futures-core",
"futures-io",
"parking",
"pin-project-lite",
]
[[package]]
name = "futures-sink"
version = "0.3.31"
@@ -887,11 +1107,24 @@ version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
[[package]]
name = "gloo-timers"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994"
dependencies = [
"futures-channel",
"futures-core",
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "glyph"
version = "0.1.0"
dependencies = [
"argon2",
"async-redis-session",
"async-session",
"axum",
"axum-extra",
@@ -901,7 +1134,8 @@ dependencies = [
"non-empty-string",
"openidconnect",
"passwords",
"redis",
"redis 0.31.0",
"redis-macros",
"serde",
"serde_json",
"serde_yaml",
@@ -943,7 +1177,7 @@ dependencies = [
"http",
"httpdate",
"mime",
"sha1",
"sha1 0.10.6",
]
[[package]]
@@ -961,6 +1195,12 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
[[package]]
name = "hex"
version = "0.4.3"
@@ -1003,7 +1243,7 @@ checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
dependencies = [
"bytes",
"fnv",
"itoa",
"itoa 1.0.15",
]
[[package]]
@@ -1060,7 +1300,7 @@ dependencies = [
"http-body",
"httparse",
"httpdate",
"itoa",
"itoa 1.0.15",
"pin-project-lite",
"smallvec",
"tokio",
@@ -1298,6 +1538,12 @@ dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "itoa"
version = "1.0.15"
@@ -1314,6 +1560,15 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "kv-log-macro"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f"
dependencies = [
"log",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
@@ -1335,6 +1590,12 @@ version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
name = "linux-raw-sys"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
[[package]]
name = "litemap"
version = "0.8.0"
@@ -1358,6 +1619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
dependencies = [
"serde",
"value-bag",
]
[[package]]
@@ -1622,6 +1884,12 @@ dependencies = [
"sha2 0.10.9",
]
[[package]]
name = "parking"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
[[package]]
name = "parking_lot"
version = "0.12.4"
@@ -1692,6 +1960,17 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "piper"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066"
dependencies = [
"atomic-waker",
"fastrand",
"futures-io",
]
[[package]]
name = "pkcs1"
version = "0.7.5"
@@ -1713,6 +1992,21 @@ dependencies = [
"spki",
]
[[package]]
name = "polling"
version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50"
dependencies = [
"cfg-if 1.0.0",
"concurrent-queue",
"hermit-abi",
"pin-project-lite",
"rustix",
"tracing",
"windows-sys 0.59.0",
]
[[package]]
name = "potential_utf"
version = "0.1.2"
@@ -1921,6 +2215,27 @@ dependencies = [
"random-number",
]
[[package]]
name = "redis"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4f0ceb2ec0dd769483ecd283f6615aa83dcd0be556d5294c6e659caefe7cc54"
dependencies = [
"async-std",
"async-trait",
"bytes",
"combine",
"dtoa",
"futures-util",
"itoa 0.4.8",
"percent-encoding",
"pin-project-lite",
"sha1 0.6.1",
"tokio",
"tokio-util 0.6.10",
"url",
]
[[package]]
name = "redis"
version = "0.31.0"
@@ -1931,7 +2246,7 @@ dependencies = [
"cfg-if 1.0.0",
"combine",
"futures-util",
"itoa",
"itoa 1.0.15",
"num-bigint",
"percent-encoding",
"pin-project-lite",
@@ -1939,10 +2254,34 @@ dependencies = [
"sha1_smol",
"socket2",
"tokio",
"tokio-util",
"tokio-util 0.7.15",
"url",
]
[[package]]
name = "redis-macros"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35ccf385c8643426649ed7de6ce3ee094a0c3bd772893aa446674496312546d0"
dependencies = [
"redis 0.31.0",
"redis-macros-derive",
"serde",
"serde_json",
]
[[package]]
name = "redis-macros-derive"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a90e7a54acf9e5462a748a4babcfc212c5142b1389103808f1116c9f54ace75c"
dependencies = [
"proc-macro2",
"quote",
"redis 0.31.0",
"syn 2.0.101",
]
[[package]]
name = "redox_syscall"
version = "0.5.12"
@@ -2058,6 +2397,19 @@ dependencies = [
"semver",
]
[[package]]
name = "rustix"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.59.0",
]
[[package]]
name = "rustls"
version = "0.23.27"
@@ -2167,7 +2519,7 @@ version = "1.0.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
dependencies = [
"itoa",
"itoa 1.0.15",
"memchr",
"ryu",
"serde",
@@ -2179,7 +2531,7 @@ version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a"
dependencies = [
"itoa",
"itoa 1.0.15",
"serde",
]
@@ -2199,7 +2551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"itoa 1.0.15",
"ryu",
"serde",
]
@@ -2241,12 +2593,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
dependencies = [
"indexmap 2.9.0",
"itoa",
"itoa 1.0.15",
"ryu",
"serde",
"unsafe-libyaml",
]
[[package]]
name = "sha1"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770"
dependencies = [
"sha1_smol",
]
[[package]]
name = "sha1"
version = "0.10.6"
@@ -2471,7 +2832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
dependencies = [
"deranged",
"itoa",
"itoa 1.0.15",
"num-conv",
"powerfmt",
"serde",
@@ -2558,6 +2919,20 @@ dependencies = [
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"log",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.15"
@@ -2709,6 +3084,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "value-bag"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5"
[[package]]
name = "version_check"
version = "0.9.5"

View File

@@ -15,6 +15,7 @@ codegen-units = 1
[dependencies]
argon2 = "0.5.3"
async-redis-session = "0.2.2"
async-session = "3.0.0"
axum = { version = "0.8.4", features = ["macros"] }
axum-extra = { version = "0.10.1", features = ["typed-header"] }
@@ -25,6 +26,7 @@ non-empty-string = { version = "0.2.6", features = ["serde"] }
openidconnect = { version = "4.0.0", features = ["reqwest"] }
passwords = "3.1.16"
redis = { version = "0.31.0", features = ["tokio-comp"] }
redis-macros = "0.5.4"
serde = "1.0.219"
serde_json = "1.0.140"
serde_yaml = "0.9.34"

View File

@@ -40,11 +40,20 @@ pub struct AutheliaConfig {
pub user_database: PathBuf,
}
#[derive(Clone, Deserialize)]
pub struct RedisConfig {
pub host: String,
pub port: u16,
#[serde(default)]
pub database: u8,
}
#[derive(Clone, Deserialize)]
pub struct Config {
pub server: ServerConfig,
pub oauth: OAuthConfig,
pub authelia: AutheliaConfig,
pub redis: RedisConfig,
}
impl Config {

View File

@@ -1,6 +1,7 @@
use std::{borrow::Cow, convert::Infallible};
use async_session::{MemoryStore, Session, SessionStore};
use async_redis_session::RedisSessionStore;
use async_session::{Session, SessionStore};
use axum::{
Json, RequestPartsExt, Router,
extract::{self, FromRef, FromRequestParts, OptionalFromRequestParts},
@@ -35,7 +36,7 @@ pub struct User {
async fn login(
extract::State(oauth_client): extract::State<OAuthClient>,
extract::State(session_store): extract::State<MemoryStore>,
extract::State(session_store): extract::State<RedisSessionStore>,
) -> Result<impl IntoResponse, StatusCode> {
let (pkce_challenge, pkce_verifier) = PkceCodeChallenge::new_random_sha256();
@@ -89,7 +90,7 @@ fn create_login_session(
}
async fn create_login_cookie(
session_store: &MemoryStore,
session_store: &RedisSessionStore,
session: Session,
) -> Result<HeaderMap, StatusCode> {
let cookie = session_store
@@ -127,9 +128,9 @@ struct CallbackParams {
async fn callback(
extract::Query(params): extract::Query<CallbackParams>,
extract::State(http_client): extract::State<reqwest::Client>,
extract::State(oauth_http_client): extract::State<reqwest::Client>,
extract::State(oauth_client): extract::State<OAuthClient>,
extract::State(session_store): extract::State<MemoryStore>,
extract::State(session_store): extract::State<RedisSessionStore>,
extract::State(config): extract::State<Config>,
TypedHeader(cookies): TypedHeader<Cookie>,
) -> Result<impl IntoResponse, StatusCode> {
@@ -155,7 +156,7 @@ async fn callback(
})?;
let token_response = validate_claims(
&http_client,
&oauth_http_client,
&oauth_client,
params,
csrf_token,
@@ -170,7 +171,7 @@ async fn callback(
error!("failed to create userinfo request: {e}");
StatusCode::INTERNAL_SERVER_ERROR
})?
.request_async(&http_client)
.request_async(&oauth_http_client)
.await
.map_err(|e| {
error!("failed to request user info: {e}");
@@ -207,7 +208,7 @@ fn retrieve_login_session(
}
async fn validate_claims(
http_client: &reqwest::Client,
oauth_http_client: &reqwest::Client,
oauth_client: &OAuthClient,
params: CallbackParams,
csrf_token: CsrfToken,
@@ -226,7 +227,7 @@ async fn validate_claims(
StatusCode::INTERNAL_SERVER_ERROR
})?
.set_pkce_verifier(pkce_verifier)
.request_async(http_client)
.request_async(oauth_http_client)
.await
.map_err(|e| {
error!("failed to request token: {e}");
@@ -313,7 +314,7 @@ fn create_user_session(
}
async fn create_user_cookie(
session_store: &MemoryStore,
session_store: &RedisSessionStore,
session: Session,
) -> Result<HeaderMap, StatusCode> {
let cookie = session_store
@@ -343,7 +344,7 @@ async fn create_user_cookie(
}
async fn logout(
extract::State(session_store): extract::State<MemoryStore>,
extract::State(session_store): extract::State<RedisSessionStore>,
TypedHeader(cookies): TypedHeader<Cookie>,
) -> Result<impl IntoResponse, StatusCode> {
let cookie = cookies.get(COOKIE_NAME).ok_or(StatusCode::UNAUTHORIZED)?;
@@ -382,13 +383,13 @@ pub fn routes(state: State) -> Router {
impl<S> FromRequestParts<S> for User
where
MemoryStore: FromRef<S>,
RedisSessionStore: FromRef<S>,
S: Send + Sync,
{
type Rejection = Response;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
let store = MemoryStore::from_ref(state);
let store = RedisSessionStore::from_ref(state);
let cookies = parts.extract::<TypedHeader<Cookie>>().await.map_err(|e| {
if *e.name() == header::COOKIE {
@@ -427,7 +428,7 @@ where
impl<S> OptionalFromRequestParts<S> for User
where
MemoryStore: FromRef<S>,
RedisSessionStore: FromRef<S>,
S: Send + Sync,
{
type Rejection = Infallible;

View File

@@ -1,8 +1,7 @@
use std::error::Error;
use async_session::MemoryStore;
use async_redis_session::RedisSessionStore;
use axum::extract::FromRef;
use log::error;
use openidconnect::{
ClientId, ClientSecret, EmptyAdditionalClaims, EndpointMaybeSet, EndpointNotSet, EndpointSet,
IssuerUrl, RedirectUrl, StandardErrorResponse,
@@ -13,12 +12,9 @@ use openidconnect::{
},
reqwest,
};
use tokio::{
spawn,
time::{Duration, sleep},
};
use redis::aio::MultiplexedConnection;
use crate::{config::Config, models::authelia};
use crate::config::Config;
pub type OAuthClient<
HasAuthUrl = EndpointSet,
@@ -52,52 +48,24 @@ pub struct State {
pub config: Config,
pub oauth_http_client: reqwest::Client,
pub oauth_client: OAuthClient,
pub session_store: MemoryStore,
pub redis_client: MultiplexedConnection,
pub session_store: RedisSessionStore,
}
impl State {
pub async fn from_config(config: Config) -> Result<Self, Box<dyn Error + Send + Sync>> {
let (oauth_http_client, oauth_client) = oauth(&config).await?;
let session_store = session_store();
let (oauth_http_client, oauth_client) = oauth_client(&config).await?;
let redis_client = redis_client(&config).await?;
let session_store = session_store(&config)?;
Ok(Self {
config,
oauth_http_client,
oauth_client,
redis_client,
session_store,
})
}
pub fn load_users(&self) -> Result<authelia::Users, Box<dyn Error + Send + Sync>> {
let file_contents = std::fs::read_to_string(&self.config.authelia.user_database)?;
let users_file: authelia::UsersFile = serde_yaml::from_str(&file_contents)?;
let users = authelia::Users::from(users_file);
Ok(users)
}
pub fn load_groups(&self) -> Result<authelia::Groups, Box<dyn Error + Send + Sync>> {
let file_contents = std::fs::read_to_string(&self.config.authelia.user_database)?;
let users_file = serde_yaml::from_str::<authelia::UsersFile>(&file_contents)?;
let groups = authelia::Groups::from(users_file);
Ok(groups)
}
pub fn load_users_and_groups(
&self,
) -> Result<(authelia::Users, authelia::Groups), Box<dyn Error + Send + Sync>> {
let file_contents = std::fs::read_to_string(&self.config.authelia.user_database)?;
let users_file = serde_yaml::from_str::<authelia::UsersFile>(&file_contents)?;
let users = authelia::Users::from(users_file.clone());
let groups = authelia::Groups::from(users_file);
Ok((users, groups))
}
pub fn save_users(&self, users: authelia::Users) -> Result<(), Box<dyn Error + Send + Sync>> {
let users_file = authelia::UsersFile::from(users);
let file_contents = serde_yaml::to_string(&users_file)?;
std::fs::write(&self.config.authelia.user_database, file_contents)?;
Ok(())
}
}
impl FromRef<State> for Config {
@@ -118,13 +86,19 @@ impl FromRef<State> for OAuthClient {
}
}
impl FromRef<State> for MemoryStore {
impl FromRef<State> for MultiplexedConnection {
fn from_ref(state: &State) -> Self {
state.redis_client.clone()
}
}
impl FromRef<State> for RedisSessionStore {
fn from_ref(state: &State) -> Self {
state.session_store.clone()
}
}
async fn oauth(
async fn oauth_client(
config: &Config,
) -> Result<(reqwest::Client, OAuthClient), Box<dyn Error + Send + Sync>> {
let oauth_http_client = reqwest::ClientBuilder::new()
@@ -151,19 +125,26 @@ async fn oauth(
Ok((oauth_http_client, oauth_client))
}
fn session_store() -> MemoryStore {
let session_store = MemoryStore::new();
async fn redis_client(
config: &Config,
) -> Result<MultiplexedConnection, Box<dyn Error + Send + Sync>> {
let url = format!(
"redis://{}:{}/{}",
config.redis.host, config.redis.port, config.redis.database
);
let session_store_clone = session_store.clone();
spawn(async move {
loop {
match session_store_clone.cleanup().await {
Ok(()) => {}
Err(e) => error!("Failed to clean up session store: {e}"),
}
sleep(Duration::from_secs(60)).await;
}
});
let client = redis::Client::open(url)?;
let connection = client.get_multiplexed_async_connection().await?;
session_store
Ok(connection)
}
fn session_store(config: &Config) -> Result<RedisSessionStore, Box<dyn Error + Send + Sync>> {
let url = format!(
"redis://{}:{}/{}",
config.redis.host, config.redis.port, config.redis.database
);
let session_store = RedisSessionStore::new(url)?.with_prefix("session:");
Ok(session_store)
}

40
src/utils/authelia.rs Normal file
View File

@@ -0,0 +1,40 @@
use std::error::Error;
use crate::{models, state::State};
impl State {
pub fn load_users(&self) -> Result<models::authelia::Users, Box<dyn Error + Send + Sync>> {
let file_contents = std::fs::read_to_string(&self.config.authelia.user_database)?;
let users_file: models::authelia::UsersFile = serde_yaml::from_str(&file_contents)?;
let users = models::authelia::Users::from(users_file);
Ok(users)
}
pub fn load_groups(&self) -> Result<models::authelia::Groups, Box<dyn Error + Send + Sync>> {
let file_contents = std::fs::read_to_string(&self.config.authelia.user_database)?;
let users_file = serde_yaml::from_str::<models::authelia::UsersFile>(&file_contents)?;
let groups = models::authelia::Groups::from(users_file);
Ok(groups)
}
pub fn load_users_and_groups(
&self,
) -> Result<(models::authelia::Users, models::authelia::Groups), Box<dyn Error + Send + Sync>>
{
let file_contents = std::fs::read_to_string(&self.config.authelia.user_database)?;
let users_file = serde_yaml::from_str::<models::authelia::UsersFile>(&file_contents)?;
let users = models::authelia::Users::from(users_file.clone());
let groups = models::authelia::Groups::from(users_file);
Ok((users, groups))
}
pub fn save_users(
&self,
users: models::authelia::Users,
) -> Result<(), Box<dyn Error + Send + Sync>> {
let users_file = models::authelia::UsersFile::from(users);
let file_contents = serde_yaml::to_string(&users_file)?;
std::fs::write(&self.config.authelia.user_database, file_contents)?;
Ok(())
}
}

View File

@@ -1 +1,2 @@
pub mod authelia;
pub mod crypto;

View File

@@ -20,6 +20,9 @@ spec:
"/etc/glyph/log4rs.yml",
]
- name: redis
image: docker.io/library/redis:latest
- name: authelia
image: docker.io/authelia/authelia:latest
volumeMounts:
@@ -90,6 +93,10 @@ data:
authelia:
user_database: /etc/authelia/users/users.yml
redis:
host: redis
port: 6379
log4rs.yml: |
appenders:
stdout: