mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 20:47:01 +01:00
feat: self cred update flow (#2995)
This commit is contained in:
parent
b53c4ba62a
commit
87b20d22d1
|
@ -36,6 +36,7 @@ pub fn view_router() -> Router<ServerState> {
|
|||
.route("/", get(|| async { Redirect::permanent("/ui/login") }))
|
||||
.route("/apps", get(apps::view_apps_get))
|
||||
.route("/reset", get(reset::view_reset_get))
|
||||
.route("/update_credentials", get(reset::view_self_reset_get))
|
||||
.route("/profile", get(profile::view_profile_get))
|
||||
.route("/profile/unlock", get(profile::view_profile_unlock_get))
|
||||
.route("/logout", get(login::view_logout_get))
|
||||
|
|
|
@ -21,7 +21,7 @@ use uuid::Uuid;
|
|||
use kanidm_proto::internal::{
|
||||
CUCredState, CUExtPortal, CUIntentToken, CURegState, CURegWarning, CURequest, CUSessionToken,
|
||||
CUStatus, CredentialDetail, OperationError, PasskeyDetail, PasswordFeedback, TotpAlgo,
|
||||
COOKIE_CU_SESSION_TOKEN,
|
||||
UserAuthToken, COOKIE_CU_SESSION_TOKEN,
|
||||
};
|
||||
|
||||
use crate::https::extractors::VerifiedClientInformation;
|
||||
|
@ -565,6 +565,65 @@ pub(crate) async fn view_new_pwd(
|
|||
.into_response())
|
||||
}
|
||||
|
||||
// Allows authenticated users to get a (cred update) or (reauth into cred update) page, depending on whether they have read write access or not respectively.
|
||||
pub(crate) async fn view_self_reset_get(
|
||||
State(state): State<ServerState>,
|
||||
Extension(kopid): Extension<KOpId>,
|
||||
HxRequest(_hx_request): HxRequest,
|
||||
VerifiedClientInformation(client_auth_info): VerifiedClientInformation,
|
||||
mut jar: CookieJar,
|
||||
) -> axum::response::Result<Response> {
|
||||
let uat: UserAuthToken = state
|
||||
.qe_r_ref
|
||||
.handle_whoami_uat(client_auth_info.clone(), kopid.eventid)
|
||||
.map_err(|op_err| HtmxError::new(&kopid, op_err))
|
||||
.await?;
|
||||
|
||||
let time = time::OffsetDateTime::now_utc() + time::Duration::new(60, 0);
|
||||
let can_rw = uat.purpose_readwrite_active(time);
|
||||
|
||||
if can_rw {
|
||||
let (cu_session_token, cu_status) = state
|
||||
.qe_w_ref
|
||||
.handle_idmcredentialupdate(client_auth_info, uat.uuid.to_string(), kopid.eventid)
|
||||
.map_err(|op_err| HtmxError::new(&kopid, op_err))
|
||||
.await?;
|
||||
|
||||
let domain_display_name = state
|
||||
.qe_r_ref
|
||||
.get_domain_display_name(kopid.eventid)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
let cu_resp = get_cu_response(domain_display_name, cu_status);
|
||||
|
||||
jar = add_cu_cookie(jar, &state, cu_session_token);
|
||||
Ok((jar, cu_resp).into_response())
|
||||
} else {
|
||||
super::login::view_reauth_get(
|
||||
state,
|
||||
client_auth_info,
|
||||
kopid,
|
||||
jar,
|
||||
"/ui/update_credentials",
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the COOKIE_CU_SESSION_TOKEN to the jar and returns the result
|
||||
fn add_cu_cookie(
|
||||
jar: CookieJar,
|
||||
state: &ServerState,
|
||||
cu_session_token: CUSessionToken,
|
||||
) -> CookieJar {
|
||||
let mut token_cookie = Cookie::new(COOKIE_CU_SESSION_TOKEN, cu_session_token.token);
|
||||
token_cookie.set_secure(state.secure_cookies);
|
||||
token_cookie.set_same_site(SameSite::Strict);
|
||||
token_cookie.set_http_only(true);
|
||||
jar.add(token_cookie)
|
||||
}
|
||||
|
||||
pub(crate) async fn view_reset_get(
|
||||
State(state): State<ServerState>,
|
||||
Extension(kopid): Extension<KOpId>,
|
||||
|
@ -622,12 +681,7 @@ pub(crate) async fn view_reset_get(
|
|||
Ok((cu_session_token, cu_status)) => {
|
||||
let cu_resp = get_cu_response(domain_display_name, cu_status);
|
||||
|
||||
let mut token_cookie = Cookie::new(COOKIE_CU_SESSION_TOKEN, cu_session_token.token);
|
||||
token_cookie.set_secure(state.secure_cookies);
|
||||
token_cookie.set_same_site(SameSite::Strict);
|
||||
token_cookie.set_http_only(true);
|
||||
jar = jar.add(token_cookie);
|
||||
|
||||
jar = add_cu_cookie(jar, &state, cu_session_token);
|
||||
Ok((jar, cu_resp).into_response())
|
||||
}
|
||||
Err(OperationError::SessionExpired) | Err(OperationError::Wait(_)) => {
|
||||
|
@ -709,7 +763,7 @@ fn get_cu_response(domain: String, cu_status: CUStatus) -> Response {
|
|||
|
||||
async fn get_cu_session(jar: CookieJar) -> Result<CUSessionToken, Response> {
|
||||
let cookie = jar.get(COOKIE_CU_SESSION_TOKEN);
|
||||
return if let Some(cookie) = cookie {
|
||||
if let Some(cookie) = cookie {
|
||||
let cu_session_token = cookie.value();
|
||||
let cu_session_token = CUSessionToken {
|
||||
token: cu_session_token.into(),
|
||||
|
@ -717,5 +771,5 @@ async fn get_cu_session(jar: CookieJar) -> Result<CUSessionToken, Response> {
|
|||
Ok(cu_session_token)
|
||||
} else {
|
||||
Err((StatusCode::FORBIDDEN, Redirect::to("/ui/reset")).into_response())
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
<path d="M9 13a1 1 0 0 1 1-1v-1a2 2 0 1 1 4 0v1a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-4a1 1 0 0 1-1-1zm3-3a1 1 0 0 0-1 1v1h2v-1a1 1 0 0 0-1-1"/>
|
||||
</svg>UNIX Password</a>
|
||||
(% endif %)
|
||||
<a href="/ui/add_new_dev" class="list-group-item list-group-item-action"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-shield-fill-plus me-3" viewBox="0 0 16 16">
|
||||
|
||||
<a href="/ui/update_credentials" class="list-group-item list-group-item-action"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-shield-fill-plus me-3" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M8 0c-.69 0-1.843.265-2.928.56-1.11.3-2.229.655-2.887.87a1.54 1.54 0 0 0-1.044 1.262c-.596 4.477.787 7.795 2.465 9.99a11.8 11.8 0 0 0 2.517 2.453c.386.273.744.482 1.048.625.28.132.581.24.829.24s.548-.108.829-.24a7 7 0 0 0 1.048-.625 11.8 11.8 0 0 0 2.517-2.453c1.678-2.195 3.061-5.513 2.465-9.99a1.54 1.54 0 0 0-1.044-1.263 63 63 0 0 0-2.887-.87C9.843.266 8.69 0 8 0m-.5 5a.5.5 0 0 1 1 0v1.5H10a.5.5 0 0 1 0 1H8.5V9a.5.5 0 0 1-1 0V7.5H6a.5.5 0 0 1 0-1h1.5z"/>
|
||||
</svg>Add another device</a>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue