Delegate session lifetime to actix-identity
crate
This commit is contained in:
parent
cb4daa1112
commit
9e72e6a044
@ -9,16 +9,13 @@ pub const DEFAULT_ADMIN_PASSWORD: &str = "admin";
|
|||||||
pub const APP_NAME: &str = "Basic OIDC";
|
pub const APP_NAME: &str = "Basic OIDC";
|
||||||
|
|
||||||
/// Maximum session duration after inactivity, in seconds
|
/// Maximum session duration after inactivity, in seconds
|
||||||
pub const MAX_INACTIVITY_DURATION: u64 = 60 * 30;
|
pub const MAX_INACTIVITY_DURATION: i64 = 60 * 30;
|
||||||
|
|
||||||
/// Minimum interval between each last activity record in session
|
/// Maximum session duration (6 hours)
|
||||||
pub const MIN_ACTIVITY_RECORD_TIME: u64 = 10;
|
pub const MAX_SESSION_DURATION: i64 = 3600 * 6;
|
||||||
|
|
||||||
/// Minimum password length
|
/// Minimum password length
|
||||||
pub const MIN_PASS_LEN: usize = 4;
|
pub const MIN_PASS_LEN: usize = 4;
|
||||||
|
|
||||||
/// Maximum session duration (6 hours)
|
|
||||||
pub const MAX_SESSION_DURATION: u64 = 3600 * 6;
|
|
||||||
|
|
||||||
/// The name of the cookie used to store session information
|
/// The name of the cookie used to store session information
|
||||||
pub const SESSION_COOKIE_NAME: &str = "auth-cookie";
|
pub const SESSION_COOKIE_NAME: &str = "auth-cookie";
|
@ -1,9 +1,7 @@
|
|||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::constants::{MAX_INACTIVITY_DURATION, MAX_SESSION_DURATION, MIN_ACTIVITY_RECORD_TIME};
|
|
||||||
use crate::data::user::{User, UserID};
|
use crate::data::user::{User, UserID};
|
||||||
use crate::utils::time::time;
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
|
||||||
pub enum SessionStatus {
|
pub enum SessionStatus {
|
||||||
@ -24,8 +22,6 @@ impl Default for SessionStatus {
|
|||||||
struct SessionIdentityData {
|
struct SessionIdentityData {
|
||||||
pub id: UserID,
|
pub id: UserID,
|
||||||
pub is_admin: bool,
|
pub is_admin: bool,
|
||||||
login_time: u64,
|
|
||||||
last_access: u64,
|
|
||||||
pub status: SessionStatus,
|
pub status: SessionStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,14 +32,12 @@ impl<'a> SessionIdentity<'a> {
|
|||||||
self.set_session_data(&SessionIdentityData {
|
self.set_session_data(&SessionIdentityData {
|
||||||
id: user.uid.clone(),
|
id: user.uid.clone(),
|
||||||
is_admin: user.admin,
|
is_admin: user.admin,
|
||||||
login_time: time(),
|
|
||||||
last_access: time(),
|
|
||||||
status: SessionStatus::SignedIn,
|
status: SessionStatus::SignedIn,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_session_data(&self) -> Option<SessionIdentityData> {
|
fn get_session_data(&self) -> Option<SessionIdentityData> {
|
||||||
let mut res: Option<SessionIdentityData> = self.0.identity()
|
let res: Option<SessionIdentityData> = self.0.identity()
|
||||||
.as_deref()
|
.as_deref()
|
||||||
.map(serde_json::from_str)
|
.map(serde_json::from_str)
|
||||||
.map(|f| match f {
|
.map(|f| match f {
|
||||||
@ -62,26 +56,6 @@ impl<'a> SessionIdentity<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(session) = res.as_mut() {
|
|
||||||
if session.login_time + MAX_SESSION_DURATION < time() {
|
|
||||||
log::info!("Session for {} reached max duration timeout", session.id);
|
|
||||||
self.0.forget();
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if session.last_access + MAX_INACTIVITY_DURATION < time() {
|
|
||||||
log::info!("Session is expired for {}", session.id);
|
|
||||||
self.0.forget();
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if session.last_access + MIN_ACTIVITY_RECORD_TIME < time() {
|
|
||||||
log::debug!("Refresh last access for session");
|
|
||||||
session.last_access = time();
|
|
||||||
self.set_session_data(session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
use actix::Actor;
|
use actix::Actor;
|
||||||
use actix_identity::{CookieIdentityPolicy, IdentityService};
|
use actix_identity::{CookieIdentityPolicy, IdentityService};
|
||||||
use actix_web::{App, get, HttpServer, web};
|
use actix_web::{App, get, HttpServer, web};
|
||||||
|
use actix_web::cookie::SameSite;
|
||||||
|
use actix_web::cookie::time::Duration;
|
||||||
use actix_web::middleware::Logger;
|
use actix_web::middleware::Logger;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
use basic_oidc::actors::users_actor::UsersActor;
|
use basic_oidc::actors::users_actor::UsersActor;
|
||||||
use basic_oidc::constants::{DEFAULT_ADMIN_PASSWORD, DEFAULT_ADMIN_USERNAME, SESSION_COOKIE_NAME};
|
use basic_oidc::constants::{DEFAULT_ADMIN_PASSWORD, DEFAULT_ADMIN_USERNAME, MAX_INACTIVITY_DURATION, MAX_SESSION_DURATION, SESSION_COOKIE_NAME};
|
||||||
use basic_oidc::controllers::assets_controller::assets_route;
|
use basic_oidc::controllers::assets_controller::assets_route;
|
||||||
use basic_oidc::controllers::login_controller::{login_route, logout_route};
|
use basic_oidc::controllers::login_controller::{login_route, logout_route};
|
||||||
use basic_oidc::data::app_config::AppConfig;
|
use basic_oidc::data::app_config::AppConfig;
|
||||||
@ -64,7 +66,10 @@ async fn main() -> std::io::Result<()> {
|
|||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
let policy = CookieIdentityPolicy::new(config.token_key.as_bytes())
|
let policy = CookieIdentityPolicy::new(config.token_key.as_bytes())
|
||||||
.name(SESSION_COOKIE_NAME)
|
.name(SESSION_COOKIE_NAME)
|
||||||
.secure(config.secure_auth_cookie);
|
.secure(config.secure_auth_cookie)
|
||||||
|
.visit_deadline(Duration::seconds(MAX_INACTIVITY_DURATION))
|
||||||
|
.login_deadline(Duration::seconds(MAX_SESSION_DURATION))
|
||||||
|
.same_site(SameSite::Strict);
|
||||||
|
|
||||||
|
|
||||||
App::new()
|
App::new()
|
||||||
|
@ -3,14 +3,10 @@
|
|||||||
use std::future::{Future, ready, Ready};
|
use std::future::{Future, ready, Ready};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use actix_identity::RequestIdentity;
|
use actix_identity::RequestIdentity;
|
||||||
|
use actix_web::{dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, Error, HttpResponse};
|
||||||
use actix_web::{dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform}, Error, FromRequest, HttpMessage, HttpResponse};
|
|
||||||
use actix_web::body::EitherBody;
|
use actix_web::body::EitherBody;
|
||||||
use actix_web::cookie::{Cookie, CookieJar};
|
|
||||||
use actix_web::http::header::http_percent_encode;
|
|
||||||
|
|
||||||
use crate::constants::SESSION_COOKIE_NAME;
|
|
||||||
|
|
||||||
// There are two steps in middleware processing.
|
// There are two steps in middleware processing.
|
||||||
// 1. Middleware initialization, middleware factory gets called with
|
// 1. Middleware initialization, middleware factory gets called with
|
||||||
@ -42,7 +38,7 @@ impl<S, B> Transform<S, ServiceRequest> for AuthMiddleware
|
|||||||
enum SessionStatus {
|
enum SessionStatus {
|
||||||
SignedOut,
|
SignedOut,
|
||||||
RegularUser,
|
RegularUser,
|
||||||
Admin
|
Admin,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AuthInnerMiddleware<S> {
|
pub struct AuthInnerMiddleware<S> {
|
||||||
@ -63,7 +59,7 @@ impl<S, B> Service<ServiceRequest> for AuthInnerMiddleware<S>
|
|||||||
|
|
||||||
forward_ready!(service);
|
forward_ready!(service);
|
||||||
|
|
||||||
fn call(&self, mut req: ServiceRequest) -> Self::Future {
|
fn call(&self, req: ServiceRequest) -> Self::Future {
|
||||||
println!("Hi from start. You requested: {}", req.path());
|
println!("Hi from start. You requested: {}", req.path());
|
||||||
|
|
||||||
let service = Rc::clone(&self.service);
|
let service = Rc::clone(&self.service);
|
||||||
|
Loading…
Reference in New Issue
Block a user