mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-11-13 20:26:52 +00:00
feat: Send account selection prompt to IDP when account switch link is clicked
This commit is contained in:
3 files changed
+21
-7
No files matched your search
@@ -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<crate::State>,
|
||||
Extension(context): Extension<TemplateContext>,
|
||||
Expect(Query(LoginQuery { next, reauthenticate })): Expect<Query<LoginQuery>>,
|
||||
Expect(Query(LoginQuery { next, reauthenticate, intent })): Expect<Query<LoginQuery>>,
|
||||
session_store: Session,
|
||||
user: User<true>,
|
||||
PostForm(form): PostForm<LoginForm>,
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
+11
-2
@@ -24,6 +24,8 @@ pub(crate) struct LoginQuery {
|
||||
pub next: Option<LoginTarget>,
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub reauthenticate: bool,
|
||||
#[serde(default)]
|
||||
pub intent: Option<LoginIntent>,
|
||||
}
|
||||
|
||||
#[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<const ALLOW_LOCKED: bool = false>(Option<UserSession>);
|
||||
|
||||
@@ -107,7 +115,7 @@ impl<const ALLOW_LOCKED: bool> User<ALLOW_LOCKED> {
|
||||
} else {
|
||||
Err(WebError::LoginRequired(LoginQuery {
|
||||
next: Some(or_else),
|
||||
reauthenticate: false,
|
||||
..Default::default()
|
||||
}))
|
||||
}
|
||||
}
|
||||
@@ -122,12 +130,13 @@ impl<const ALLOW_LOCKED: bool> User<ALLOW_LOCKED> {
|
||||
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()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user