mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-07 08:02:40 +00:00
feat: branch on MIN_VERSION to write plaintext token or null
Check MIN_VERSION_SUPPORTS_TOKEN_HASH at runtime: write plaintext to token column while old workers exist, switch to NULL once all workers are >= 1.649.0. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
e2103d9448
commit
23bc2c4eee
@@ -514,12 +514,21 @@ pub async fn create_token_internal(
|
||||
) -> Result<String> {
|
||||
use tracing::Instrument;
|
||||
use windmill_audit::{audit_oss::audit_log, ActionKind};
|
||||
use windmill_common::{utils::rd_string, worker::CLOUD_HOSTED};
|
||||
use windmill_common::{
|
||||
min_version::MIN_VERSION_SUPPORTS_TOKEN_HASH, utils::rd_string, worker::CLOUD_HOSTED,
|
||||
};
|
||||
|
||||
let token = rd_string(32);
|
||||
let t_hash = hash_token(&token);
|
||||
let t_prefix = &token[..TOKEN_PREFIX_LEN];
|
||||
|
||||
// Write plaintext token column until all workers support hash-based lookup
|
||||
let plaintext: Option<&str> = if MIN_VERSION_SUPPORTS_TOKEN_HASH.met().await {
|
||||
None
|
||||
} else {
|
||||
Some(&token)
|
||||
};
|
||||
|
||||
let is_super_admin = sqlx::query_scalar!(
|
||||
"SELECT super_admin FROM password WHERE email = $1",
|
||||
authed.email
|
||||
@@ -548,7 +557,7 @@ pub async fn create_token_internal(
|
||||
)",
|
||||
t_hash,
|
||||
t_prefix,
|
||||
&token,
|
||||
plaintext as Option<&str>,
|
||||
authed.email,
|
||||
token_config.label,
|
||||
token_config.expiration,
|
||||
|
||||
@@ -1746,9 +1746,16 @@ pub async fn create_session_token<'c>(
|
||||
tx: &mut sqlx::Transaction<'c, sqlx::Postgres>,
|
||||
cookies: Cookies,
|
||||
) -> Result<String> {
|
||||
use windmill_common::min_version::MIN_VERSION_SUPPORTS_TOKEN_HASH;
|
||||
|
||||
let token = rd_string(32);
|
||||
let t_hash = windmill_common::auth::hash_token(&token);
|
||||
let t_prefix = &token[..TOKEN_PREFIX_LEN];
|
||||
let plaintext: Option<&str> = if MIN_VERSION_SUPPORTS_TOKEN_HASH.met().await {
|
||||
None
|
||||
} else {
|
||||
Some(&token)
|
||||
};
|
||||
|
||||
if *INVALIDATE_OLD_SESSIONS {
|
||||
sqlx::query!(
|
||||
@@ -1782,7 +1789,7 @@ pub async fn create_session_token<'c>(
|
||||
VALUES ($1, $2, $3, $4, $5, now() + ($6 || ' seconds')::interval, $7)",
|
||||
t_hash,
|
||||
t_prefix,
|
||||
&token,
|
||||
plaintext as Option<&str>,
|
||||
email,
|
||||
"session",
|
||||
&MAX_SESSION_VALIDITY_SECONDS.to_string(),
|
||||
@@ -1827,9 +1834,16 @@ async fn impersonate(
|
||||
authed: ApiAuthed,
|
||||
Json(new_token): Json<NewToken>,
|
||||
) -> Result<(StatusCode, String)> {
|
||||
use windmill_common::min_version::MIN_VERSION_SUPPORTS_TOKEN_HASH;
|
||||
|
||||
let token = rd_string(32);
|
||||
let t_hash = windmill_common::auth::hash_token(&token);
|
||||
let t_prefix = &token[..TOKEN_PREFIX_LEN];
|
||||
let plaintext: Option<&str> = if MIN_VERSION_SUPPORTS_TOKEN_HASH.met().await {
|
||||
None
|
||||
} else {
|
||||
Some(&token)
|
||||
};
|
||||
require_super_admin(&db, &authed.email).await?;
|
||||
|
||||
if new_token.impersonate_email.is_none() {
|
||||
@@ -1855,7 +1869,7 @@ async fn impersonate(
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7)",
|
||||
t_hash,
|
||||
t_prefix,
|
||||
&token,
|
||||
plaintext as Option<&str>,
|
||||
impersonated,
|
||||
new_token.label,
|
||||
new_token.expiration,
|
||||
|
||||
@@ -12,6 +12,7 @@ use sqlx::FromRow;
|
||||
use windmill_common::{
|
||||
auth::{hash_token, TOKEN_PREFIX_LEN},
|
||||
error::{Error, Result},
|
||||
min_version::MIN_VERSION_SUPPORTS_TOKEN_HASH,
|
||||
utils::rd_string,
|
||||
BASE_URL, DB,
|
||||
};
|
||||
@@ -386,6 +387,11 @@ async fn handle_authorization_code_grant(
|
||||
let access_token = rd_string(32);
|
||||
let access_token_hash = hash_token(&access_token);
|
||||
let access_token_prefix = &access_token[..TOKEN_PREFIX_LEN];
|
||||
let plaintext: Option<&str> = if MIN_VERSION_SUPPORTS_TOKEN_HASH.met().await {
|
||||
None
|
||||
} else {
|
||||
Some(&access_token)
|
||||
};
|
||||
let refresh_token = rd_string(32);
|
||||
let token_family = sqlx::types::Uuid::new_v4();
|
||||
let scopes = auth_code.scopes;
|
||||
@@ -397,7 +403,7 @@ async fn handle_authorization_code_grant(
|
||||
WHERE NOT EXISTS(SELECT 1 FROM workspace WHERE id = $8 AND deleted = true)",
|
||||
access_token_hash,
|
||||
access_token_prefix,
|
||||
&access_token,
|
||||
plaintext as Option<&str>,
|
||||
auth_code.user_email,
|
||||
format!("mcp-oauth-{}", auth_code.client_id),
|
||||
MCP_OAUTH_TOKEN_EXPIRATION_SECS.to_string(),
|
||||
@@ -525,6 +531,11 @@ async fn handle_refresh_token_grant(
|
||||
let new_access_token = rd_string(32);
|
||||
let new_access_token_hash = hash_token(&new_access_token);
|
||||
let new_access_token_prefix = &new_access_token[..TOKEN_PREFIX_LEN];
|
||||
let new_plaintext: Option<&str> = if MIN_VERSION_SUPPORTS_TOKEN_HASH.met().await {
|
||||
None
|
||||
} else {
|
||||
Some(&new_access_token)
|
||||
};
|
||||
let new_refresh_token = rd_string(32);
|
||||
let scopes = token_row.scopes;
|
||||
|
||||
@@ -535,7 +546,7 @@ async fn handle_refresh_token_grant(
|
||||
WHERE NOT EXISTS(SELECT 1 FROM workspace WHERE id = $8 AND deleted = true)",
|
||||
new_access_token_hash,
|
||||
new_access_token_prefix,
|
||||
&new_access_token,
|
||||
new_plaintext as Option<&str>,
|
||||
token_row.user_email,
|
||||
format!("mcp-oauth-{}", token_row.client_id),
|
||||
MCP_OAUTH_TOKEN_EXPIRATION_SECS.to_string(),
|
||||
|
||||
Reference in New Issue
Block a user