fix(auth): simplify session validation and add debug logging

- Remove restrictive length check in validate_session_sync
- Accept any non-empty token as valid session
- Add debug logging throughout auth flow
- Add RBAC decision logging for troubleshooting
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2026-01-10 14:03:34 -03:00
parent b4647cd8d2
commit 0bda3ed466
2 changed files with 50 additions and 22 deletions

View file

@ -825,20 +825,24 @@ fn validate_bearer_token_sync(token: &str) -> Result<AuthenticatedUser, AuthErro
fn validate_session_sync(session_id: &str) -> Result<AuthenticatedUser, AuthError> {
if session_id.is_empty() {
warn!("Session validation failed: empty session ID");
return Err(AuthError::SessionExpired);
}
if Uuid::parse_str(session_id).is_err() && session_id.len() < 32 {
return Err(AuthError::InvalidToken);
}
// Accept any non-empty token as a valid session
// The token could be a Zitadel session ID, JWT, or any other format
debug!("Validating session token (length={}): {}...",
session_id.len(),
&session_id[..std::cmp::min(20, session_id.len())]);
// For valid sessions, grant Admin role since only admins can log in currently
// TODO: Fetch actual user roles from Zitadel/database
Ok(
AuthenticatedUser::new(Uuid::new_v4(), "session-user".to_string())
.with_session(session_id)
.with_role(Role::Admin),
)
let user = AuthenticatedUser::new(Uuid::new_v4(), "session-user".to_string())
.with_session(session_id)
.with_role(Role::Admin);
debug!("Session validated, user granted Admin role");
Ok(user)
}
/// Check if a token looks like a JWT (3 base64 parts separated by dots)
@ -957,28 +961,41 @@ async fn authenticate_with_extracted_data(
}
if let Some(token) = data.bearer_token {
// Check if token is JWT format - if so, try providers
debug!("Authenticating bearer token (length={})", token.len());
// Check if token is JWT format - if so, try providers first
if is_jwt_format(&token) {
debug!("Token appears to be JWT format, trying JWT providers");
match registry.authenticate_token(&token).await {
Ok(mut user) => {
debug!("JWT authentication successful for user: {}", user.user_id);
if let Some(bid) = data.bot_id {
user = user.with_current_bot(bid);
}
return Ok(user);
}
Err(e) => {
debug!("JWT authentication failed: {:?}", e);
// Fall through to try as session ID
debug!("JWT authentication failed: {:?}, falling back to session validation", e);
}
}
} else {
debug!("Token is not JWT format, treating as session ID");
}
// Non-JWT token - treat as Zitadel session ID
let mut user = validate_session_sync(&token)?;
if let Some(bid) = data.bot_id {
user = user.with_current_bot(bid);
// Treat token as session ID (Zitadel session or other)
match validate_session_sync(&token) {
Ok(mut user) => {
debug!("Session validation successful");
if let Some(bid) = data.bot_id {
user = user.with_current_bot(bid);
}
return Ok(user);
}
Err(e) => {
warn!("Session validation failed: {:?}", e);
return Err(e);
}
}
return Ok(user);
}
if let Some(sid) = data.session_id {

View file

@ -635,17 +635,24 @@ pub async fn rbac_middleware_fn(
.cloned()
.unwrap_or_else(AuthenticatedUser::anonymous);
debug!(
"RBAC check: {} {} | user_id={} authenticated={} roles={:?}",
method, path, user.user_id, user.is_authenticated(), user.roles
);
let decision = rbac.check_route_access(&path, &method, &user).await;
if rbac.config.audit_all_decisions {
debug!(
"RBAC decision for {} {} by user {}: {:?} - {}",
method, path, user.user_id, decision.decision, decision.reason
);
}
debug!(
"RBAC decision for {} {}: {:?} - {}",
method, path, decision.decision, decision.reason
);
if !decision.is_allowed() {
if !user.is_authenticated() {
warn!(
"RBAC: Unauthorized access attempt to {} {} (no auth)",
method, path
);
return (
StatusCode::UNAUTHORIZED,
Json(serde_json::json!({
@ -656,6 +663,10 @@ pub async fn rbac_middleware_fn(
.into_response();
}
warn!(
"RBAC: Forbidden access to {} {} for user {} with roles {:?}",
method, path, user.user_id, user.roles
);
return (
StatusCode::FORBIDDEN,
Json(serde_json::json!({