修复多端登录互相顶号

单设备退出只撤销当前 refresh session,不再提升账号级 token_version

认证中间件和 refresh 接口在本进程未命中会话时按需刷新 SpacetimeDB 认证工作集

补充多端登录与跨进程会话补水回归测试

同步项目文档和 Hermes 共享决策记录
This commit is contained in:
2026-06-07 20:54:35 +08:00
parent a5143fa0cb
commit cc84656a1f
9 changed files with 463 additions and 55 deletions

View File

@@ -7,6 +7,7 @@ use module_auth::{RefreshSessionError, RotateRefreshSessionInput};
use platform_auth::hash_refresh_session_token;
use shared_contracts::auth::RefreshSessionResponse;
use time::OffsetDateTime;
use tracing::warn;
use crate::{
api_response::json_success_body,
@@ -39,16 +40,48 @@ pub async fn refresh_session(
let next_refresh_token = platform_auth::create_refresh_session_token();
let next_refresh_token_hash = hash_refresh_session_token(&next_refresh_token);
let rotated = state
.refresh_session_service()
.rotate_session(
RotateRefreshSessionInput {
refresh_token_hash,
next_refresh_token_hash,
},
OffsetDateTime::now_utc(),
)
.map_err(|error| map_refresh_error_with_clear_cookie(&state, error))?;
let rotated = match state.refresh_session_service().rotate_session(
RotateRefreshSessionInput {
refresh_token_hash: refresh_token_hash.clone(),
next_refresh_token_hash: next_refresh_token_hash.clone(),
},
OffsetDateTime::now_utc(),
) {
Ok(rotated) => rotated,
Err(RefreshSessionError::SessionNotFound) => {
match state.refresh_auth_store_from_spacetime().await {
Ok(true) => {}
Ok(false) => {
return Err(map_refresh_error_with_clear_cookie(
&state,
RefreshSessionError::SessionNotFound,
));
}
Err(error) => {
warn!(
request_id = request_context.request_id(),
error = %error,
"refresh session 本地未命中后刷新认证工作集失败"
);
return Err(map_refresh_error_with_clear_cookie(
&state,
RefreshSessionError::SessionNotFound,
));
}
}
state
.refresh_session_service()
.rotate_session(
RotateRefreshSessionInput {
refresh_token_hash,
next_refresh_token_hash,
},
OffsetDateTime::now_utc(),
)
.map_err(|error| map_refresh_error_with_clear_cookie(&state, error))?
}
Err(error) => return Err(map_refresh_error_with_clear_cookie(&state, error)),
};
let access_token = sign_access_token_for_user(
&state,
&rotated.user,