diff --git a/src/web/oidc/authorize.rs b/src/web/oidc/authorize.rs index 43a7c176..1e851234 100644 --- a/src/web/oidc/authorize.rs +++ b/src/web/oidc/authorize.rs @@ -12,7 +12,7 @@ pub struct AuthorizationQuery { pub code_challenge: String, pub code_challenge_method: String, pub response_type: String, - pub response_mode: String, + pub response_mode: Option, } impl From for AuthorizationQuery { @@ -37,7 +37,7 @@ impl From for AuthorizationQuery { code_challenge, code_challenge_method, response_type, - response_mode, + response_mode: Some(response_mode), } } } diff --git a/src/web/oidc/consent.rs b/src/web/oidc/consent.rs index dee03140..ba95dc86 100644 --- a/src/web/oidc/consent.rs +++ b/src/web/oidc/consent.rs @@ -26,6 +26,11 @@ pub fn oidc_consent_form(hostname: &str, query: &AuthorizationQuery) -> OidcResp /// Render the html contents of the user consent page. fn consent_page(hostname: &str, query: &AuthorizationQuery, route: &str, nonce: &str) -> String { + let response_mode = &query.response_mode.clone() + .unwrap_or_else(|| match query.redirect_uri.scheme() { + | "https" => "fragment", + | _ => "query" + }); let template = ConsentPageTemplate { nonce, hostname, @@ -37,7 +42,7 @@ fn consent_page(hostname: &str, query: &AuthorizationQuery, route: &str, nonce: code_challenge: &encode(query.code_challenge.as_str()), code_challenge_method: &encode(query.code_challenge_method.as_str()), response_type: &encode(query.response_type.as_str()), - response_mode: &encode(query.response_mode.as_str()), + response_mode: &encode(response_mode), }; template.render().expect("consent page render") diff --git a/src/web/oidc/login.rs b/src/web/oidc/login.rs index 40eeede5..e8008710 100644 --- a/src/web/oidc/login.rs +++ b/src/web/oidc/login.rs @@ -58,12 +58,16 @@ impl TryFrom for LoginQuery { let Some(response_type) = body.unique_value("response_type") else { return Err(LoginError("missing field: response_type".to_owned())); }; - let Some(response_mode) = body.unique_value("response_mode") else { - return Err(LoginError("missing field: response_mode".to_owned())); - }; let Ok(redirect_uri) = Url::from_str(&redirect_uri) else { return Err(LoginError("invalid field: redirect_uri".to_owned())); }; + // response_mode is not strictly needed : its value defaults to "fragment" + // when over https. It's required by the spec but Fractal doesn't provide it. + let response_mode = body.unique_value("response_mode") + .unwrap_or_else(|| match redirect_uri.scheme() { + | "https" => "fragment", + | _ => "query" + }); Ok(Self { username: username.to_string(), @@ -101,6 +105,12 @@ pub fn oidc_login_form(hostname: &str, query: &AuthorizationQuery) -> OidcRespon /// Render the html contents of the login page. fn login_page(hostname: &str, query: &AuthorizationQuery, route: &str, nonce: &str) -> String { + let response_mode = &query.response_mode + .clone() + .unwrap_or_else(|| match query.redirect_uri.scheme() { + | "https" => "fragment".to_string(), + | _ => "query".to_string() + }); let template = LoginPageTemplate { nonce, hostname, @@ -112,7 +122,7 @@ fn login_page(hostname: &str, query: &AuthorizationQuery, route: &str, nonce: &s code_challenge: query.code_challenge.as_str(), code_challenge_method: query.code_challenge_method.as_str(), response_type: query.response_type.as_str(), - response_mode: query.response_mode.as_str(), + response_mode, }; template.render().expect("login template render")