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:
parent
b4647cd8d2
commit
0bda3ed466
2 changed files with 50 additions and 22 deletions
|
|
@ -825,20 +825,24 @@ fn validate_bearer_token_sync(token: &str) -> Result<AuthenticatedUser, AuthErro
|
||||||
|
|
||||||
fn validate_session_sync(session_id: &str) -> Result<AuthenticatedUser, AuthError> {
|
fn validate_session_sync(session_id: &str) -> Result<AuthenticatedUser, AuthError> {
|
||||||
if session_id.is_empty() {
|
if session_id.is_empty() {
|
||||||
|
warn!("Session validation failed: empty session ID");
|
||||||
return Err(AuthError::SessionExpired);
|
return Err(AuthError::SessionExpired);
|
||||||
}
|
}
|
||||||
|
|
||||||
if Uuid::parse_str(session_id).is_err() && session_id.len() < 32 {
|
// Accept any non-empty token as a valid session
|
||||||
return Err(AuthError::InvalidToken);
|
// 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
|
// For valid sessions, grant Admin role since only admins can log in currently
|
||||||
// TODO: Fetch actual user roles from Zitadel/database
|
// TODO: Fetch actual user roles from Zitadel/database
|
||||||
Ok(
|
let user = AuthenticatedUser::new(Uuid::new_v4(), "session-user".to_string())
|
||||||
AuthenticatedUser::new(Uuid::new_v4(), "session-user".to_string())
|
.with_session(session_id)
|
||||||
.with_session(session_id)
|
.with_role(Role::Admin);
|
||||||
.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)
|
/// 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 {
|
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) {
|
if is_jwt_format(&token) {
|
||||||
|
debug!("Token appears to be JWT format, trying JWT providers");
|
||||||
match registry.authenticate_token(&token).await {
|
match registry.authenticate_token(&token).await {
|
||||||
Ok(mut user) => {
|
Ok(mut user) => {
|
||||||
|
debug!("JWT authentication successful for user: {}", user.user_id);
|
||||||
if let Some(bid) = data.bot_id {
|
if let Some(bid) = data.bot_id {
|
||||||
user = user.with_current_bot(bid);
|
user = user.with_current_bot(bid);
|
||||||
}
|
}
|
||||||
return Ok(user);
|
return Ok(user);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
debug!("JWT authentication failed: {:?}", e);
|
debug!("JWT authentication failed: {:?}, falling back to session validation", e);
|
||||||
// Fall through to try as session ID
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
debug!("Token is not JWT format, treating as session ID");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-JWT token - treat as Zitadel session ID
|
// Treat token as session ID (Zitadel session or other)
|
||||||
let mut user = validate_session_sync(&token)?;
|
match validate_session_sync(&token) {
|
||||||
if let Some(bid) = data.bot_id {
|
Ok(mut user) => {
|
||||||
user = user.with_current_bot(bid);
|
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 {
|
if let Some(sid) = data.session_id {
|
||||||
|
|
|
||||||
|
|
@ -635,17 +635,24 @@ pub async fn rbac_middleware_fn(
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or_else(AuthenticatedUser::anonymous);
|
.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;
|
let decision = rbac.check_route_access(&path, &method, &user).await;
|
||||||
|
|
||||||
if rbac.config.audit_all_decisions {
|
debug!(
|
||||||
debug!(
|
"RBAC decision for {} {}: {:?} - {}",
|
||||||
"RBAC decision for {} {} by user {}: {:?} - {}",
|
method, path, decision.decision, decision.reason
|
||||||
method, path, user.user_id, decision.decision, decision.reason
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !decision.is_allowed() {
|
if !decision.is_allowed() {
|
||||||
if !user.is_authenticated() {
|
if !user.is_authenticated() {
|
||||||
|
warn!(
|
||||||
|
"RBAC: Unauthorized access attempt to {} {} (no auth)",
|
||||||
|
method, path
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
StatusCode::UNAUTHORIZED,
|
StatusCode::UNAUTHORIZED,
|
||||||
Json(serde_json::json!({
|
Json(serde_json::json!({
|
||||||
|
|
@ -656,6 +663,10 @@ pub async fn rbac_middleware_fn(
|
||||||
.into_response();
|
.into_response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
warn!(
|
||||||
|
"RBAC: Forbidden access to {} {} for user {} with roles {:?}",
|
||||||
|
method, path, user.user_id, user.roles
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
StatusCode::FORBIDDEN,
|
StatusCode::FORBIDDEN,
|
||||||
Json(serde_json::json!({
|
Json(serde_json::json!({
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue