diff --git a/proto b/proto index cd1afb7..f812030 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit cd1afb727774b51118c470fafbb5efd808e4d405 +Subproject commit f812030f490945a5a029f11c46e006103c4e8ab1 diff --git a/src/handlers/mfa_config.rs b/src/handlers/mfa_config.rs index 31c9703..fde697a 100644 --- a/src/handlers/mfa_config.rs +++ b/src/handlers/mfa_config.rs @@ -8,8 +8,8 @@ use crate::{ proto::{ CodeMfaSetupFinishRequest, CodeMfaSetupFinishResponse, CodeMfaSetupStartRequest, CodeMfaSetupStartResponse, DeviceInfo, MfaConfigAuthorizeRequest, - MfaConfigAuthorizeResponse, MfaConfigSendCodeRequest, MfaConfigStartRequest, - MfaConfigStartResponse, core_request, core_response, + MfaConfigAuthorizeResponse, MfaConfigEndRequest, MfaConfigSendCodeRequest, + MfaConfigStartRequest, MfaConfigStartResponse, core_request, core_response, }, }; @@ -21,6 +21,7 @@ pub(crate) fn router() -> Router { .route("/authorize", post(authorize_mfa_config)) .route("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/setup/start", post(start_mfa_setup)) .route("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/setup/finish", post(finish_mfa_setup)) + .route("/end", post(end_mfa_config)) } #[instrument(level = "debug", skip(state, req))] @@ -97,3 +98,23 @@ async fn finish_mfa_setup( ) -> Result, ApiError> { code_mfa_setup_finish(&state, device_info, req).await } + +/// Ends the whole MFA configuration session. +#[instrument(level = "debug", skip(state, req))] +async fn end_mfa_config( + State(state): State, + device_info: DeviceInfo, + Json(req): Json, +) -> Result<(), ApiError> { + info!("Ending MFA configuration session"); + let rx = state + .grpc_server + .send(core_request::Payload::MfaConfigEnd(req), device_info)?; + let payload = get_core_response(rx, None).await?; + if let core_response::Payload::Empty(()) = payload { + Ok(()) + } else { + error!("Received invalid gRPC response type, expected Empty"); + Err(ApiError::InvalidResponseType) + } +} diff --git a/src/tests/mfa_config.rs b/src/tests/mfa_config.rs index d4f25a1..8bd7a05 100644 --- a/src/tests/mfa_config.rs +++ b/src/tests/mfa_config.rs @@ -62,6 +62,10 @@ fn fallback_then_totp( recovery_codes: vec!["aaaa-bbbb".into(), "cccc-dddd".into()], }) } + core_request::Payload::MfaConfigEnd(req) => { + assert_eq!(req.session_token, SESSION_TOKEN); + core_response::Payload::Empty(()) + } _ => panic!("unexpected request to Core"), } } @@ -119,9 +123,17 @@ async fn test_mfa_config_flow_forwards_session_token() { assert_eq!(status, StatusCode::OK, "{body}"); assert_eq!(body["recovery_codes"], json!(["aaaa-bbbb", "cccc-dddd"])); + let (status, body) = post_json( + &app, + "/api/v1/mfa-config/end", + &json!({ "session_token": session_token }), + ) + .await; + assert_eq!(status, StatusCode::OK, "{body}"); + assert_eq!( steps.load(Ordering::Relaxed), - 5, + 6, "Core must see every step once" ); }