Skip to content

Commit 5c33d76

Browse files
committed
first pass at always including current URI in login_url
1 parent 92b870a commit 5c33d76

File tree

2 files changed

+14
-17
lines changed

2 files changed

+14
-17
lines changed

nexus/src/external_api/console_api.rs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -496,17 +496,15 @@ pub struct LoginUrlQuery {
496496
/// Generate URL to IdP login form. Optional `state` param is included in query
497497
/// string if present, and will typically represent the URL to send the user
498498
/// back to after successful login.
499-
pub fn get_login_url(state: Option<String>) -> String {
499+
fn get_login_url(state: Option<String>) -> String {
500500
// assume state is not URL encoded, so no risk of double encoding (dropshot
501501
// decodes it on the way in)
502502
let query = match state {
503503
Some(state) if state.is_empty() => None,
504-
Some(state) => Some(
504+
Some(state) => {
505505
serde_urlencoded::to_string(LoginUrlQuery { state: Some(state) })
506-
// unwrap is safe because query.state was just deserialized out
507-
// of a query param, so we know it's serializable
508-
.unwrap(),
509-
),
506+
.ok() // in the hard-to-imagine event it's not serializable, no query
507+
}
510508
None => None,
511509
};
512510
// Once we have IdP integration, this will be a URL for the IdP login page.
@@ -563,25 +561,21 @@ pub async fn console_index_or_login_redirect(
563561
) -> Result<Response<Body>, HttpError> {
564562
let opctx = OpContext::for_external_api(&rqctx).await;
565563

566-
// if authed, serve HTML page with bundle in script tag
567-
568-
// HTML doesn't need to be static -- we'll probably find a reason to do some
569-
// minimal templating, e.g., putting a CSRF token in the page
570-
571-
// amusingly, at least to start out, I don't think we care about the path
572-
// because the real routing is all client-side. we serve the same HTML
573-
// regardless, the app starts on the client and renders the right page and
574-
// makes the right API requests.
564+
// if authed, serve console index.html with JS bundle in script tag
575565
if let Ok(opctx) = opctx {
576566
if opctx.authn.actor().is_some() {
577567
return serve_console_index(rqctx.context()).await;
578568
}
579569
}
580570

581571
// otherwise redirect to idp
572+
573+
// put the current URI in the query string to redirect back to after login
574+
let uri = rqctx.request.lock().await.uri().clone();
575+
582576
Ok(Response::builder()
583577
.status(StatusCode::FOUND)
584-
.header(http::header::LOCATION, get_login_url(None))
578+
.header(http::header::LOCATION, get_login_url(Some(uri.to_string())))
585579
.body("".into())?)
586580
}
587581

nexus/tests/integration_tests/console_api.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,10 @@ async fn test_console_pages(cptestctx: &ControlPlaneTestContext) {
116116
// request to console page route without auth should redirect to IdP
117117
let _ = RequestBuilder::new(&testctx, Method::GET, "/orgs/irrelevant-path")
118118
.expect_status(Some(StatusCode::FOUND))
119-
.expect_response_header(header::LOCATION, "/spoof_login")
119+
.expect_response_header(
120+
header::LOCATION,
121+
"/spoof_login?state=%2Forgs%2Firrelevant-path",
122+
)
120123
.execute()
121124
.await
122125
.expect("failed to redirect to IdP on auth failure");

0 commit comments

Comments
 (0)