Skip to content

Commit ca86cff

Browse files
committed
simplify OIDC infinite redirect prevention logic
This update introduces a new function, `handle_oidc_callback_error`, to streamline error handling during OIDC callback processing. It enhances the management of redirect counts and separates the logic for handling maximum redirect limits into `handle_max_redirect_count_reached`. Additionally, the `build_auth_provider_redirect_response` function is updated to accept the redirect count, ensuring accurate tracking of redirects. This refactor aims to prevent infinite redirect loops and improve code clarity.
1 parent 24110bc commit ca86cff

File tree

1 file changed

+45
-27
lines changed

1 file changed

+45
-27
lines changed

src/webserver/oidc.rs

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,9 @@ async fn handle_unauthenticated_request(
403403
log::debug!("Redirecting to OIDC provider");
404404

405405
let initial_url = request.uri().to_string();
406-
let response = build_auth_provider_redirect_response(oidc_state, &initial_url).await;
406+
let redirect_count = get_redirect_count(&request);
407+
let response =
408+
build_auth_provider_redirect_response(oidc_state, &initial_url, redirect_count).await;
407409
MiddlewareResponse::Respond(request.into_response(response))
408410
}
409411

@@ -413,25 +415,40 @@ async fn handle_oidc_callback(oidc_state: &OidcState, request: ServiceRequest) -
413415
clear_redirect_count_cookie(&mut response);
414416
request.into_response(response)
415417
}
416-
Err(e) => {
417-
let redirect_count = get_redirect_count(&request);
418-
if redirect_count >= MAX_OIDC_REDIRECTS {
419-
log::error!(
420-
"Failed to process OIDC callback after {redirect_count} attempts. \
421-
Stopping to avoid infinite redirections: {e:#}"
422-
);
423-
let resp = build_oidc_error_response(&request, &e);
424-
return request.into_response(resp);
425-
}
426-
log::error!("Failed to process OIDC callback (attempt {redirect_count}). Refreshing oidc provider metadata, then redirecting to home page: {e:#}");
427-
oidc_state.refresh_on_error(&request).await;
428-
let mut resp = build_auth_provider_redirect_response(oidc_state, "/").await;
429-
set_redirect_count_cookie(&mut resp, redirect_count + 1);
430-
request.into_response(resp)
431-
}
418+
Err(e) => handle_oidc_callback_error(oidc_state, request, e).await,
432419
}
433420
}
434421

422+
async fn handle_oidc_callback_error(
423+
oidc_state: &OidcState,
424+
request: ServiceRequest,
425+
e: anyhow::Error,
426+
) -> ServiceResponse {
427+
let redirect_count = get_redirect_count(&request);
428+
if redirect_count >= MAX_OIDC_REDIRECTS {
429+
return handle_max_redirect_count_reached(request, &e, redirect_count);
430+
}
431+
log::error!(
432+
"Failed to process OIDC callback (attempt {redirect_count}). Refreshing oidc provider metadata, then redirecting to home page: {e:#}"
433+
);
434+
oidc_state.refresh_on_error(&request).await;
435+
let resp = build_auth_provider_redirect_response(oidc_state, "/", redirect_count).await;
436+
request.into_response(resp)
437+
}
438+
439+
fn handle_max_redirect_count_reached(
440+
request: ServiceRequest,
441+
e: &anyhow::Error,
442+
redirect_count: u8,
443+
) -> ServiceResponse {
444+
log::error!(
445+
"Failed to process OIDC callback after {redirect_count} attempts. \
446+
Stopping to avoid infinite redirections: {e:#}"
447+
);
448+
let resp = build_oidc_error_response(&request, e);
449+
request.into_response(resp)
450+
}
451+
435452
async fn handle_oidc_logout(oidc_state: &OidcState, request: ServiceRequest) -> ServiceResponse {
436453
match process_oidc_logout(oidc_state, &request).await {
437454
Ok(response) => request.into_response(response),
@@ -684,12 +701,23 @@ fn set_auth_cookie(response: &mut HttpResponse, id_token: &OidcToken) {
684701
async fn build_auth_provider_redirect_response(
685702
oidc_state: &OidcState,
686703
initial_url: &str,
704+
redirect_count: u8,
687705
) -> HttpResponse {
688706
let AuthUrl { url, params } = build_auth_url(oidc_state).await;
689707
let tmp_login_flow_state_cookie = create_tmp_login_flow_state_cookie(&params, initial_url);
708+
let redirect_count_cookie = Cookie::build(
709+
SQLPAGE_OIDC_REDIRECT_COUNT_COOKIE,
710+
(redirect_count + 1).to_string(),
711+
)
712+
.path("/")
713+
.http_only(true)
714+
.same_site(actix_web::cookie::SameSite::Lax)
715+
.max_age(LOGIN_FLOW_STATE_COOKIE_EXPIRATION)
716+
.finish();
690717
HttpResponse::SeeOther()
691718
.append_header((header::LOCATION, url.to_string()))
692719
.cookie(tmp_login_flow_state_cookie)
720+
.cookie(redirect_count_cookie)
693721
.body("Redirecting...")
694722
}
695723

@@ -706,16 +734,6 @@ fn get_redirect_count(request: &ServiceRequest) -> u8 {
706734
.unwrap_or(0)
707735
}
708736

709-
fn set_redirect_count_cookie(response: &mut HttpResponse, count: u8) {
710-
let cookie = Cookie::build(SQLPAGE_OIDC_REDIRECT_COUNT_COOKIE, count.to_string())
711-
.path("/")
712-
.http_only(true)
713-
.same_site(actix_web::cookie::SameSite::Lax)
714-
.max_age(LOGIN_FLOW_STATE_COOKIE_EXPIRATION)
715-
.finish();
716-
response.add_cookie(&cookie).ok();
717-
}
718-
719737
fn clear_redirect_count_cookie(response: &mut HttpResponse) {
720738
let cookie = Cookie::build(SQLPAGE_OIDC_REDIRECT_COUNT_COOKIE, "")
721739
.path("/")

0 commit comments

Comments
 (0)