diff --git a/src/web/pages/account/login.rs b/src/web/pages/account/login.rs index 5f1db34ff..c2079ac1e 100644 --- a/src/web/pages/account/login.rs +++ b/src/web/pages/account/login.rs @@ -26,7 +26,7 @@ use crate::{ oidc::{OIDC_SESSION_ID_KEY, OidcSession, OidcSessionState}, }, response, - session::{LoginQuery, LoginTarget, User, UserSession}, + session::{LoginIntent, LoginQuery, LoginTarget, User, UserSession}, template, }; @@ -74,7 +74,7 @@ struct LoginForm { async fn route_login( State(services): State, Extension(context): Extension, - Expect(Query(LoginQuery { next, reauthenticate })): Expect>, + Expect(Query(LoginQuery { next, reauthenticate, intent })): Expect>, session_store: Session, user: User, PostForm(form): PostForm, @@ -84,7 +84,11 @@ async fn route_login( let login_type = if services.oidc.enabled() { let (session, redirect_url) = services .oidc - .begin_session(reauthenticate.then(|| CoreAuthPrompt::Consent)) + .begin_session(match intent { + | Some(LoginIntent::SwitchAccounts) => Some(CoreAuthPrompt::SelectAccount), + | _ if reauthenticate => Some(CoreAuthPrompt::Consent), + | _ => None, + }) .await; session_store diff --git a/src/web/pages/oauth/grant.rs b/src/web/pages/oauth/grant.rs index 1ec5dae9d..aa2825e1d 100644 --- a/src/web/pages/oauth/grant.rs +++ b/src/web/pages/oauth/grant.rs @@ -17,7 +17,7 @@ use crate::{ components::{Avatar, AvatarType, ClientScopes}, }, response, - session::{LoginQuery, LoginTarget, User}, + session::{LoginIntent, LoginQuery, LoginTarget, User}, template, }; @@ -129,7 +129,8 @@ async fn route_authorization_code( context, serde_urlencoded::to_string(LoginQuery { next: Some(LoginTarget::AuthorizationCode(query)), - reauthenticate: false, + intent: Some(LoginIntent::SwitchAccounts), + ..Default::default() }) .unwrap(), user_id, diff --git a/src/web/session/mod.rs b/src/web/session/mod.rs index 6bb1ba4df..526915243 100644 --- a/src/web/session/mod.rs +++ b/src/web/session/mod.rs @@ -24,6 +24,8 @@ pub(crate) struct LoginQuery { pub next: Option, #[serde(default, skip_serializing_if = "std::ops::Not::not")] pub reauthenticate: bool, + #[serde(default)] + pub intent: Option, } #[derive(Clone, Debug, Default, Deserialize, Serialize)] @@ -65,6 +67,12 @@ impl LoginTarget { } } +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "snake_case")] +pub(crate) enum LoginIntent { + SwitchAccounts, +} + /// An extractor that fetches the authenticated user. pub(crate) struct User(Option); @@ -107,7 +115,7 @@ impl User { } else { Err(WebError::LoginRequired(LoginQuery { next: Some(or_else), - reauthenticate: false, + ..Default::default() })) } } @@ -122,12 +130,13 @@ impl User { Err(WebError::LoginRequired(LoginQuery { next: Some(or_else), reauthenticate: true, + ..Default::default() })) } } else { Err(WebError::LoginRequired(LoginQuery { next: Some(or_else), - reauthenticate: false, + ..Default::default() })) } }