mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-20 16:02:19 +00:00
feat: more controls on setting token duration (#5421)
* allow setting max session length * more options for expiration * sqlx * option to invalidate all old sessions on new session * sqlx update script on mac * order * add audit log --------- Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
This commit is contained in:
+14
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "DELETE FROM token WHERE email = $1 AND label = 'session'",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "7db681e86f8332c636d0f29b389860292b704788827edfebc467a92486f9e14f"
|
||||
}
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "INSERT INTO token\n (token, email, label, expiration, super_admin)\n VALUES ($1, $2, $3, now() + ($4 || ' hours')::interval, $5)",
|
||||
"query": "INSERT INTO token\n (token, email, label, expiration, super_admin)\n VALUES ($1, $2, $3, now() + ($4 || ' seconds')::interval, $5)",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
@@ -14,5 +14,5 @@
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "b05c5f62ef4aa21d33369130cced0e9d7d128727eb58a9be7ae69cbb16bcbb27"
|
||||
"hash": "8aebd7f7fd1374f1c3d5389e953ebf080df3f76ac3e6e6373a89c8d46388125d"
|
||||
}
|
||||
@@ -55,7 +55,6 @@ use windmill_common::{
|
||||
utils::{not_found_if_none, rd_string, require_admin, Pagination, StripPath},
|
||||
};
|
||||
use windmill_git_sync::handle_deployment_metadata;
|
||||
pub const TTL_TOKEN_DB_H: u32 = 72;
|
||||
|
||||
const COOKIE_PATH: &str = "/";
|
||||
|
||||
@@ -1696,6 +1695,11 @@ async fn refresh_token(
|
||||
Ok("token refreshed".to_string())
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref MAX_SESSION_VALIDITY_SECONDS: i64 = std::env::var("MAX_SESSION_VALIDITY_SECONDS").ok().unwrap_or_else(|| String::new()).parse::<i64>().unwrap_or(3 * 24 * 60 * 60);
|
||||
static ref INVALIDATE_OLD_SESSIONS: bool = std::env::var("INVALIDATE_OLD_SESSIONS").ok().unwrap_or_else(|| String::new()).parse::<bool>().unwrap_or(false);
|
||||
}
|
||||
|
||||
pub async fn create_session_token<'c>(
|
||||
email: &str,
|
||||
super_admin: bool,
|
||||
@@ -1703,18 +1707,45 @@ pub async fn create_session_token<'c>(
|
||||
cookies: Cookies,
|
||||
) -> Result<String> {
|
||||
let token = rd_string(32);
|
||||
|
||||
if *INVALIDATE_OLD_SESSIONS {
|
||||
sqlx::query!(
|
||||
"DELETE FROM token WHERE email = $1 AND label = 'session'",
|
||||
email
|
||||
)
|
||||
.execute(&mut **tx)
|
||||
.await?;
|
||||
|
||||
audit_log(
|
||||
&mut **tx,
|
||||
&AuditAuthor {
|
||||
email: email.to_string(),
|
||||
username: email.to_string(),
|
||||
username_override: None,
|
||||
},
|
||||
"users.token.invalidate_old_sessions",
|
||||
ActionKind::Delete,
|
||||
&"global",
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.instrument(tracing::info_span!("token", email))
|
||||
.await?;
|
||||
}
|
||||
|
||||
sqlx::query!(
|
||||
"INSERT INTO token
|
||||
(token, email, label, expiration, super_admin)
|
||||
VALUES ($1, $2, $3, now() + ($4 || ' hours')::interval, $5)",
|
||||
VALUES ($1, $2, $3, now() + ($4 || ' seconds')::interval, $5)",
|
||||
token,
|
||||
email,
|
||||
"session",
|
||||
TTL_TOKEN_DB_H.to_string(),
|
||||
&MAX_SESSION_VALIDITY_SECONDS.to_string(),
|
||||
super_admin
|
||||
)
|
||||
.execute(&mut **tx)
|
||||
.await?;
|
||||
|
||||
let mut cookie = Cookie::new(COOKIE_NAME, token.clone());
|
||||
cookie.set_secure(IS_SECURE.read().await.clone());
|
||||
cookie.set_same_site(Some(tower_cookies::cookie::SameSite::Lax));
|
||||
@@ -1725,7 +1756,7 @@ pub async fn create_session_token<'c>(
|
||||
}
|
||||
|
||||
let mut expire: OffsetDateTime = time::OffsetDateTime::now_utc();
|
||||
expire += time::Duration::days(3);
|
||||
expire += time::Duration::seconds(*MAX_SESSION_VALIDITY_SECONDS);
|
||||
cookie.set_expires(expire);
|
||||
cookies.add(cookie);
|
||||
Ok(token)
|
||||
|
||||
@@ -72,8 +72,7 @@
|
||||
newToken = undefined
|
||||
let date: Date | undefined
|
||||
if (newTokenExpiration) {
|
||||
date = new Date()
|
||||
date.setDate(date.getDate() + newTokenExpiration)
|
||||
date = new Date(new Date().getTime() + newTokenExpiration * 1000)
|
||||
}
|
||||
newToken = await UserService.createToken({
|
||||
requestBody: {
|
||||
@@ -299,9 +298,13 @@
|
||||
</label>
|
||||
<select bind:value={newTokenExpiration}>
|
||||
<option value={undefined}>No expiration</option>
|
||||
<option value={7}>7d</option>
|
||||
<option value={30}>30d</option>
|
||||
<option value={90}>90d</option>
|
||||
<option value={15*60}>15m</option>
|
||||
<option value={30*60}>30m</option>
|
||||
<option value={1*60*60}>1h</option>
|
||||
<option value={1*24*60*60}>1d</option>
|
||||
<option value={7*24*60*60}>7d</option>
|
||||
<option value={30*24*60*60}>30d</option>
|
||||
<option value={90*24*60*60}>90d</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex items-end">
|
||||
|
||||
Reference in New Issue
Block a user