Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 20 additions & 15 deletions crates/defguard_core/src/grpc/proxy/client_mfa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@ use defguard_proto::{
ClientMfaFinishRequest, ClientMfaFinishResponse, ClientMfaStartRequest,
ClientMfaStartResponse, MfaAdvanced, MfaAwaitingExternal, MfaBiometricSignature,
MfaCodeCredential, MfaCompleted, MfaFido2Assertion, MfaFido2Challenge,
MfaFlowApproveRequest, MfaFlowRemoteRequest, MfaFlowRemoteResponse, MfaFlowStartAccepted,
MfaFlowStartRejected, MfaFlowStartRequest, MfaFlowStartResponse, MfaFlowStepFinishRequest,
MfaFlowStepFinishResponse, MfaFlowStepStartRequest, MfaFlowStepStartResponse, MfaMethod,
MfaSignatureChallenge, MfaStartRejectionReason, MfaStepRejection, MfaStepResult,
MfaStepStarted, mfa_flow_start_response, mfa_flow_step_finish_request, mfa_step_result,
mfa_step_started,
MfaFlowApproveRequest, MfaFlowRemoteRejected, MfaFlowRemoteRequest, MfaFlowRemoteResponse,
MfaFlowStartAccepted, MfaFlowStartRejected, MfaFlowStartRequest, MfaFlowStartResponse,
MfaFlowStepFinishRequest, MfaFlowStepFinishResponse, MfaFlowStepStartRequest,
MfaFlowStepStartResponse, MfaMethod, MfaRemoteRejectionReason, MfaSignatureChallenge,
MfaStartRejectionReason, MfaStepRejection, MfaStepResult, MfaStepStarted,
mfa_flow_remote_response, mfa_flow_start_response, mfa_flow_step_finish_request,
mfa_step_result, mfa_step_started,
},
enterprise::posture::{DevicePostureCheckRequest, DevicePostureData},
proxy::{
Expand Down Expand Up @@ -1065,14 +1066,18 @@ impl ClientMfaServer {
.await
}
Ok(Ok(RemoteAuthSignal::MobileClientOutdated)) => {
remove_waiter_and_send_error(
&waiters,
&hash,
&waiter_identity,
&response_tx,
request_id,
Status::failed_precondition(LEGACY_MOBILE_CLIENT_MESSAGE),
);
remove_remote_mfa_waiter(&waiters, &hash, &waiter_identity);
let _ = response_tx.send(CoreResponse {
id: request_id,
payload: Some(Payload::MfaFlowRemote(MfaFlowRemoteResponse {
outcome: Some(mfa_flow_remote_response::Outcome::Rejected(
MfaFlowRemoteRejected {
reason: MfaRemoteRejectionReason::MfaRemoteRejectionMobileClientOutdated
.into(),
},
)),
})),
});
return;
}
Ok(Ok(RemoteAuthSignal::Superseded)) => {
Expand Down Expand Up @@ -1122,7 +1127,7 @@ impl ClientMfaServer {
Payload::CoreError(Status::internal("mobile approval did not complete").into())
}
Ok(outcome) => Payload::MfaFlowRemote(MfaFlowRemoteResponse {
result: Some(outcome.into()),
outcome: Some(mfa_flow_remote_response::Outcome::Result(outcome.into())),
}),
Err(error) => Payload::CoreError(Status::from(error).into()),
};
Expand Down
18 changes: 9 additions & 9 deletions crates/defguard_core/src/grpc/proxy/client_mfa/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ use defguard_proto::{
ClientMfaFinishRequest, ClientMfaStartRequest, MfaCodeCredential, MfaFlowApproveRequest,
MfaFlowRemoteRequest, MfaFlowStartRequest, MfaFlowStepFinishRequest,
MfaFlowStepStartRequest, MfaMethod, MfaMobileApprovalProof, MfaStartRejectionReason,
mfa_flow_start_response, mfa_flow_step_finish_request, mfa_step_result, mfa_step_started,
mfa_flow_remote_response, mfa_flow_start_response, mfa_flow_step_finish_request,
mfa_step_result, mfa_step_started,
},
enterprise::posture::{BoolCheck, DevicePostureCheckRequest, DevicePostureData, bool_check},
proxy::{ClientMfaOidcAuthenticateRequest, ClientMfaTokenValidationRequest, DeviceInfo},
Expand Down Expand Up @@ -2077,9 +2078,9 @@ async fn test_mfa_flow_remote_wakes_matching_attempt_and_delivers_psk(
let Some(super::Payload::MfaFlowRemote(response)) = response.payload else {
panic!("expected a typed remote flow response");
};
let result = response
.result
.expect("remote response must include a result");
let Some(mfa_flow_remote_response::Outcome::Result(result)) = response.outcome else {
panic!("remote response must include a result");
};
let Some(mfa_step_result::Outcome::Completed(completed)) = result.outcome else {
panic!("expected a completed remote result");
};
Expand Down Expand Up @@ -2208,11 +2209,10 @@ async fn test_mfa_flow_remote_observes_approval_before_registration(
let Some(super::Payload::MfaFlowRemote(response)) = response.payload else {
panic!("expected a typed remote flow response");
};
let Some(mfa_step_result::Outcome::Completed(completed)) = response
.result
.expect("remote response must include a result")
.outcome
else {
let Some(mfa_flow_remote_response::Outcome::Result(result)) = response.outcome else {
panic!("remote response must include a result");
};
let Some(mfa_step_result::Outcome::Completed(completed)) = result.outcome else {
panic!("expected a completed remote result");
};
assert_ne!(completed.preshared_key, "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ use defguard_proto::{
client_types::{
ClientMfaFinishRequest, ClientMfaStartRequest, MfaBiometricSignature, MfaCodeCredential,
MfaFlowApproveRequest, MfaFlowRemoteRequest, MfaFlowStartRequest, MfaFlowStepFinishRequest,
MfaFlowStepStartRequest, MfaMethod, MfaMobileApprovalProof, MfaStepResult,
mfa_flow_start_response, mfa_flow_step_finish_request, mfa_step_result, mfa_step_started,
MfaFlowStepStartRequest, MfaMethod, MfaMobileApprovalProof, MfaRemoteRejectionReason,
MfaStepResult, mfa_flow_remote_response, mfa_flow_start_response,
mfa_flow_step_finish_request, mfa_step_result, mfa_step_started,
},
proxy::{CoreRequest, CoreResponse, core_request, core_response},
};
Expand Down Expand Up @@ -257,9 +258,10 @@ fn flow_step_result(response: CoreResponse) -> MfaStepResult {

fn flow_remote_result(response: CoreResponse) -> MfaStepResult {
match response.payload {
Some(core_response::Payload::MfaFlowRemote(response)) => response
.result
.expect("remote finish must include a result"),
Some(core_response::Payload::MfaFlowRemote(response)) => match response.outcome {
Some(mfa_flow_remote_response::Outcome::Result(result)) => result,
_ => panic!("remote finish must include a result"),
},
Some(core_response::Payload::CoreError(error)) => panic!(
"remote finish failed with status={} msg={}",
error.status_code, error.message
Expand Down Expand Up @@ -686,10 +688,17 @@ async fn test_legacy_mfa_finish_rejects_valid_multi_step_mobile_proof(
assert_eq!(remote.id, 2);
assert_eq!(phone.id, 3);

let (remote_code, remote_message) = assert_error_response_details(&remote);
let Some(core_response::Payload::MfaFlowRemote(response)) = remote.payload else {
panic!("expected MfaFlowRemote rejection");
};
let Some(mfa_flow_remote_response::Outcome::Rejected(rejected)) = response.outcome else {
panic!("expected outdated mobile client rejection");
};
assert_eq!(
rejected.reason(),
MfaRemoteRejectionReason::MfaRemoteRejectionMobileClientOutdated
);
let (phone_code, phone_message) = assert_error_response_details(&phone);
assert_eq!(remote_code, Code::FailedPrecondition);
assert_eq!(remote_message, LEGACY_MOBILE_CLIENT_MESSAGE);
assert_eq!(phone_code, Code::FailedPrecondition);
assert_eq!(phone_message, LEGACY_MOBILE_CLIENT_MESSAGE);

Expand Down
1 change: 1 addition & 0 deletions deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ feature-depth = 1
# output a note when they are encountered.
ignore = [
{ id = "RUSTSEC-2023-0071", reason = "https://github.com/RustCrypto/RSA/issues/19" },
{ id = "RUSTSEC-2026-0387", reason = "Transitive dependency of jsonwebtoken" },
]
# If this is true, then cargo deny will use the git executable to fetch advisory database.
# If this is false, then it uses a built-in git library.
Expand Down
2 changes: 1 addition & 1 deletion proto
Loading