authkestra_engine/auth/
session.rs1use crate::auth::error::AuthError;
2use crate::auth::state::Identity;
3use crate::auth::SameSite;
4use async_trait::async_trait;
5use serde::{Deserialize, Serialize};
6
7#[derive(Clone, Debug)]
9pub struct SessionConfig {
10 pub cookie_name: String,
12 pub secure: bool,
14 pub http_only: bool,
16 pub same_site: SameSite,
18 pub path: String,
20 pub max_age: Option<chrono::Duration>,
22 pub state_encryption_key: [u8; 32],
25}
26
27impl Default for SessionConfig {
28 fn default() -> Self {
29 let mut key = [0u8; 32];
30 key.copy_from_slice(b"static_key_change_in_production!");
34
35 Self {
36 cookie_name: "authkestra_session".to_string(),
37 secure: true,
38 http_only: true,
39 same_site: SameSite::Lax,
40 path: "/".to_string(),
41 max_age: Some(chrono::Duration::hours(24)),
42 state_encryption_key: key,
43 }
44 }
45}
46
47#[derive(Clone, Debug, Serialize, Deserialize)]
49#[non_exhaustive]
50pub struct Session {
51 pub id: String,
53 pub identity: Identity,
55 pub expires_at: chrono::DateTime<chrono::Utc>,
57}
58
59#[async_trait]
61pub trait SessionStore: Send + Sync + 'static {
62 async fn load_session(&self, id: &str) -> Result<Option<Session>, AuthError>;
64 async fn save_session(&self, session: &Session) -> Result<(), AuthError>;
66 async fn delete_session(&self, id: &str) -> Result<(), AuthError>;
68}
69
70#[async_trait]
71impl<S: crate::store::KvStore<Session>> SessionStore for S {
72 async fn load_session(&self, id: &str) -> Result<Option<Session>, AuthError> {
73 self.get(id)
74 .await
75 .map_err(|e| AuthError::Session(e.to_string()))
76 }
77
78 async fn save_session(&self, session: &Session) -> Result<(), AuthError> {
79 let ttl_secs = (session.expires_at - chrono::Utc::now()).num_seconds();
80 let ttl = std::time::Duration::from_secs(if ttl_secs > 0 { ttl_secs as u64 } else { 0 });
81 self.set(&session.id, session.clone(), ttl)
82 .await
83 .map_err(|e| AuthError::Session(e.to_string()))
84 }
85
86 async fn delete_session(&self, id: &str) -> Result<(), AuthError> {
87 self.delete(id)
88 .await
89 .map_err(|e| AuthError::Session(e.to_string()))
90 }
91}
92
93impl Session {
94 pub fn new(id: String, identity: Identity, expires_at: chrono::DateTime<chrono::Utc>) -> Self {
96 Self {
97 id,
98 identity,
99 expires_at,
100 }
101 }
102}