From 6f3443f2ca2ff3ed84802164d226e3add24ebf4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Wed, 16 Sep 2026 16:47:03 +0200 Subject: [PATCH 1/5] add flow-specific messages --- common/client_types.proto | 153 ++++++++++++++++++-------------------- v2/proxy.proto | 28 +++---- 2 files changed, 87 insertions(+), 94 deletions(-) diff --git a/common/client_types.proto b/common/client_types.proto index 790e31d..f033c06 100644 --- a/common/client_types.proto +++ b/common/client_types.proto @@ -50,15 +50,15 @@ message InitialUserInfo { } message EnrollmentSettings { - // Vpn step is skippable + // VPN step is skippable. bool vpn_setup_optional = 1; - // Manual WireGuard setup is disabled + // Manual WireGuard setup is disabled. bool only_client_activation = 2; - // Only admins can add devices so vpn step is skipped + // Only admins can add devices, so the VPN step is skipped. bool admin_device_management = 3; - // Enable Email method for MFA setup + // Enable email as an MFA setup method. bool smtp_configured = 4; - // MFA setup is not skippable + // MFA setup is not skippable. bool mfa_required = 5; } @@ -121,7 +121,7 @@ message DeviceConfig { string config = 3; string endpoint = 4; string assigned_ip = 5; - // network pubkey + // Network public key. string pubkey = 6; string allowed_ips = 7; optional string dns = 8; @@ -134,9 +134,8 @@ message DeviceConfig { // Omitted (along with the location) when incompatible. optional LocationMfaMode location_mfa_mode = 11 [deprecated = true]; optional ServiceLocationMode service_location_mode = 12; - // added for 2.1 optional bool posture_check_required = 13; - // [2.2] The ordered steps of the MFA flow resolved for this user at this + // The ordered steps of the MFA flow resolved for this user at this // location. repeated MfaStep steps = 14; } @@ -158,12 +157,11 @@ message InstanceInfo { bool disable_all_traffic = 7 [deprecated = true]; optional string openid_display_name = 8; optional ClientTrafficPolicy client_traffic_policy = 9; - // Added for 2.1 // When ANY enrolled instance has this true, the desktop // client and CLI hide, block, and disconnect bare WireGuard tunnels // (OR-across-instances semantics). optional bool disable_tunnels = 10; - // [2.2] Lightweight summary of the enrolled user's configured MFA methods. + // Lightweight summary of the enrolled user's configured MFA methods. // Used for quick checks (e.g. "does this user have any MFA methods?"). MfaUserState mfa_user_state = 11; } @@ -209,7 +207,7 @@ enum MfaMethod { FIDO2 = 5; } -// Multi-step MFA (added for 2.2) +// Multi-step MFA message MfaStepMethod { MfaMethod method = 1; @@ -230,6 +228,32 @@ message MfaUserState { repeated MfaMethod configured_methods = 1; } +message MfaSignatureChallenge { + string challenge = 1; +} + +message MfaFido2Challenge { + string challenge = 1; + repeated string credential_ids = 2; +} + +message MfaStepStarted { + string step_attempt_id = 1; + oneof challenge { + MfaSignatureChallenge signature = 2; + MfaFido2Challenge fido2 = 3; + } +} + +message MfaFlowStartAccepted { + string token = 1; + MfaStepStarted first_step = 2; +} + +message MfaFlowStartRejected { + repeated MfaStepRejection rejections = 1; +} + // Why a step of the submitted plan was refused at Start. Every reason names one // specific step. A plan whose length does not match the resolved flow is a // malformed request and is refused with an INVALID_ARGUMENT status instead of @@ -264,17 +288,16 @@ message MfaCompleted { } // An out-of-band step has not resolved yet: the OIDC callback has not arrived, -// or the mobile approval has not been given. Not a failure - the client keeps -// waiting, and it does not count against the attempt limit. +// or the mobile approval has not been given. This is not a failure. The client +// keeps waiting, and it does not count against the attempt limit. message MfaAwaitingExternal {} -// Step failures are NOT carried here. They are returned as gRPC error statuses. -// -// ClientMfaFinishResponse is shared with pre-2.2 clients, and those gate on the -// status alone: the desktop client connects the tunnel on any OK response, and -// configures the peer with no preshared key when one is absent. An OK response +// Step failures are NOT carried here. New-flow adapters return them as gRPC +// error statuses. The legacy ClientMfaFinishResponse remains top-level PSK-only: +// pre-2.2 clients gate on the status alone, connect the tunnel on any OK response, +// and configure the peer with no preshared key when one is absent. An OK result // carrying a failure would let a deployed client treat a rejected factor as -// success. The status code is the protection, not the deprecation marker. +// success. message MfaStepResult { oneof outcome { MfaAdvanced advanced = 1; @@ -283,88 +306,58 @@ message MfaStepResult { } } -message ClientMfaStepStartRequest { +message ClientMfaFlowStartRequest { + int64 location_id = 1; + string pubkey = 2; + optional defguard.enterprise.posture.v2.DevicePostureData posture_data = 3; + repeated MfaMethod selected_methods = 4; +} + +message ClientMfaFlowStartResponse { + oneof outcome { + MfaFlowStartAccepted accepted = 1; + MfaFlowStartRejected rejected = 2; + } +} + +message ClientMfaFlowStepStartRequest { string token = 1; MfaMethod method = 2; } -// Returned only when the step actually started; failures are gRPC error -// statuses, mapped as described on MfaStepResult. -message ClientMfaStepStartResponse { - // Nonce identifying this attempt at the current step. The client round-trips - // it through the OIDC state parameter and the mobile-approve payload so late - // callbacks can be matched against the attempt that is actually current. - string step_attempt_id = 1; - // Biometric or mobile-approve challenge, when the method needs one. - // [2.2] For FIDO2 this holds the challenge the key has to sign. - optional string challenge = 2; - // [2.2] For FIDO2: the credentials registered for this user, base64url as - // webauthn-rs serializes them. The client offers the whole list to the key, - // which answers for the one it holds, and names it in the finish request so - // later attempts can be narrowed to that credential. - repeated string credential_ids = 3; +message ClientMfaFlowStepStartResponse { + MfaStepStarted started = 1; } +// LEGACY/FROZEN: preserve this message's wire contract for deployed clients. message ClientMfaStartRequest { int64 location_id = 1; string pubkey = 2; - // Legacy single-step path. Read ONLY when selected_methods is empty. - // - // Never test this field for presence. MfaMethod.TOTP is 0 and pre-2.2 clients - // encode with implicit presence, so a legacy client selecting TOTP omits the - // field entirely - "absent" and "TOTP" are indistinguishable on the wire. The - // proto3 default of 0 is the correct reading in both cases. - // DEPRECATED(2.2): superseded by selected_methods (MfaCompleted.preshared_key) - MfaMethod method = 3 [deprecated = true]; - // [2.1] Required when the location has posture policies assigned. + // MfaMethod.TOTP is 0, so an omitted value and explicit TOTP are equivalent. + MfaMethod method = 3; + // Required when the location has posture policies assigned. optional defguard.enterprise.posture.v2.DevicePostureData posture_data = 4; - // [2.2] Multi-step path: the client's full per-step method plan, one entry - // per step in flow order - index i is the chosen method for step i. - // Non-empty is the SOLE discriminator between the multi-step flow and the - // legacy fused Start + StepStart adapter. A length that does not match the - // resolved flow is refused with an INVALID_ARGUMENT status. - repeated MfaMethod selected_methods = 5; -} - -// Flat presence-routed fields rather than a oneof, unlike -// ClientMfaStepStartResponse: this message predates 2.2, so token and challenge -// are already parsed by deployed clients and cannot be moved inside a oneof. -// repeated fields cannot live in a oneof either. +} + +// LEGACY/FROZEN: preserve this message's wire contract for deployed clients. message ClientMfaStartResponse { string token = 1; - // for biometric mfa method (legacy fused path only) + // Initial biometric or mobile-approve challenge. optional string challenge = 2; - // [2.2] Per-step rejections, sparse - only failing steps appear. Non-empty - // means the plan was refused and no session was created. - repeated MfaStepRejection rejections = 3; - // [2.2] For FIDO2 on the legacy fused path: the credentials registered for - // this user, alongside the challenge above. - repeated string credential_ids = 4; } +// LEGACY/FROZEN: preserve this message's wire contract for deployed clients. message ClientMfaFinishRequest { string token = 1; optional string code = 2; - // [2.2] For FIDO2 this holds the signature. + // Public key used for mobile approval. optional string auth_pub_key = 3; - // [2.2] The attempt id minted by StepStart for the step being submitted. It binds - // this proof to a specific attempt, so a stale or duplicate proof cannot advance - // the step twice. Optional so pre-2.2 clients that omit it still parse; a None - // value keeps the legacy single-step path working. - optional string step_attempt_id = 4; - // [2.2] FIDO2 - optional bytes auth_data = 5; - // [2.2] For FIDO2: which credential actually signed. Picked by the key out of the list - // it was offered, so Core knows which of the user's security keys is in use. - optional bytes credential_id = 6; } +// LEGACY/FROZEN: preserve this message's wire contract for deployed clients. message ClientMfaFinishResponse { - // DEPRECATED(2.2): superseded by result (MfaCompleted.preshared_key) - string preshared_key = 1 [deprecated = true]; + string preshared_key = 1; optional string token = 2; - // [2.2] Outcome of the step just submitted. - MfaStepResult result = 3; } message RegisterMobileAuthRequest { @@ -379,7 +372,7 @@ message CodeMfaSetupStartRequest { string token = 2; } -// in case of email secret is empty +// The TOTP secret is empty for the email method. message CodeMfaSetupStartResponse { optional string totp_secret = 1; } @@ -394,7 +387,7 @@ message CodeMfaSetupFinishResponse { repeated string recovery_codes = 1; } -// [2.2] MFA factor configuration for an enrolled device. +// MFA factor configuration for an enrolled device. // Authenticate with the device's polling token and public key. message MfaConfigStartRequest { string token = 1; diff --git a/v2/proxy.proto b/v2/proxy.proto index c9e4743..20098f7 100644 --- a/v2/proxy.proto +++ b/v2/proxy.proto @@ -68,11 +68,9 @@ message AwaitRemoteMfaFinishRequest { string token = 1; } +// LEGACY/FROZEN: preserve this message's wire contract for deployed clients. message AwaitRemoteMfaFinishResponse { - // DEPRECATED(2.2): superseded by result (MfaCompleted.preshared_key) - string preshared_key = 1 [deprecated = true]; - // [2.2] Outcome of the remote-approved step. - defguard.client_types.MfaStepResult result = 2; + string preshared_key = 1; } message InitialInfo { @@ -81,8 +79,8 @@ message InitialInfo { /* * Error response variant. - * Due to reverse proxy -> core communication this is how we - * can return gRPC errors from core. + * The proxy-to-core stream is reversed, so core returns gRPC errors + * through this message. */ message CoreError { int32 status_code = 1; @@ -90,7 +88,7 @@ message CoreError { } /* - * CoreResponse represents messages send from core to proxy + * CoreResponse represents messages sent from core to proxy * in response to CoreRequest. */ message CoreResponse { @@ -116,10 +114,11 @@ message CoreResponse { defguard.enterprise.posture.v2.DevicePostureCheckResponse device_posture_check = 19; defguard.enterprise.posture.v2.DevicePostureRejection device_posture_rejected = 20; PublicSettings public_settings = 21; - defguard.client_types.ClientMfaStepStartResponse client_mfa_step_start = 22; defguard.client_types.MfaConfigStartResponse mfa_config_start = 23; defguard.client_types.MfaConfigAuthorizeResponse mfa_config_authorize = 24; defguard.client_types.MfaConfigSendCodeResponse mfa_config_send_code = 25; + defguard.client_types.ClientMfaFlowStartResponse client_mfa_flow_start = 26; + defguard.client_types.ClientMfaFlowStepStartResponse client_mfa_flow_step_start = 27; } } @@ -131,7 +130,7 @@ message HttpsCerts { message PublicSettings { bool display_password_reset = 1; bool display_download_step = 2; - // Public URL the Edge component is reached at. + // Public URL used to reach the Edge component. optional string public_url = 3; } @@ -179,7 +178,7 @@ message AcmeLogs { } /* - * Wrapper message streamed by IssueAcme. + * Wrapper message streamed by TriggerAcme. * Carries either a progress update, the final certificate, or (on failure) * the collected proxy log lines. */ @@ -192,7 +191,7 @@ message AcmeIssueEvent { } /* - * CoreRequest represents messages send from proxy to core. + * CoreRequest represents messages sent from proxy to core. */ message CoreRequest { uint64 id = 1; @@ -218,10 +217,11 @@ message CoreRequest { AwaitRemoteMfaFinishRequest await_remote_mfa_finish = 20; AcmeCertificate acme_certificate = 21; defguard.enterprise.posture.v2.DevicePostureCheckRequest device_posture_check = 22; - defguard.client_types.ClientMfaStepStartRequest client_mfa_step_start = 23; defguard.client_types.MfaConfigStartRequest mfa_config_start = 24; defguard.client_types.MfaConfigAuthorizeRequest mfa_config_authorize = 25; defguard.client_types.MfaConfigSendCodeRequest mfa_config_send_code = 26; + defguard.client_types.ClientMfaFlowStartRequest client_mfa_flow_start = 28; + defguard.client_types.ClientMfaFlowStepStartRequest client_mfa_flow_step_start = 29; } } @@ -244,8 +244,8 @@ service Proxy { rpc TriggerAcme(AcmeChallenge) returns (stream AcmeIssueEvent); } -// Service used for initial Proxy setup, for configuring TLS certificate -// on Proxy for gRPC communication. +// Service used during initial Proxy setup to configure the TLS certificate +// for gRPC communication. service ProxySetup { rpc Start(google.protobuf.Empty) returns (stream defguard.common.v2.LogEntry); rpc GetCsr(defguard.common.v2.CertificateInfo) returns (defguard.common.v2.DerPayload); From 5d6a3f19f8b08f2b350b1521244feb1557d32af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Fri, 18 Sep 2026 18:07:35 +0200 Subject: [PATCH 2/5] add MFA step-related messages --- common/client_types.proto | 52 +++++++++++++++++++++++++++++++++++++++ v2/proxy.proto | 5 ++++ 2 files changed, 57 insertions(+) diff --git a/common/client_types.proto b/common/client_types.proto index f033c06..21a80db 100644 --- a/common/client_types.proto +++ b/common/client_types.proto @@ -329,6 +329,58 @@ message ClientMfaFlowStepStartResponse { MfaStepStarted started = 1; } +message MfaCodeCredential { + string code = 1; +} + +message MfaBiometricSignature { + string signature = 1; +} + +// CTAP-native binary fields. Carries no clientDataJSON. +message MfaFido2Assertion { + bytes rp_id_hash = 1; + bytes authenticator_data = 2; + bytes signature = 3; + bytes credential_id = 4; +} + +// The session's persisted method selects the verifier. An unset submission is +// valid only for OIDC and MobileApprove polling. +message ClientMfaFlowStepFinishRequest { + string token = 1; + string step_attempt_id = 2; + oneof submission { + MfaCodeCredential code = 3; + MfaBiometricSignature biometric = 4; + MfaFido2Assertion fido2 = 5; + } +} + +message ClientMfaFlowStepFinishResponse { + MfaStepResult result = 1; +} + +message ClientMfaFlowRemoteRequest { + string token = 1; + string step_attempt_id = 2; +} + +message ClientMfaFlowRemoteResponse { + MfaStepResult result = 1; +} + +message MfaMobileApprovalProof { + string signature = 1; + string auth_pub_key = 2; +} + +message ClientMfaFlowApproveRequest { + string token = 1; + string step_attempt_id = 2; + MfaMobileApprovalProof proof = 3; +} + // LEGACY/FROZEN: preserve this message's wire contract for deployed clients. message ClientMfaStartRequest { int64 location_id = 1; diff --git a/v2/proxy.proto b/v2/proxy.proto index 20098f7..76842ea 100644 --- a/v2/proxy.proto +++ b/v2/proxy.proto @@ -119,6 +119,8 @@ message CoreResponse { defguard.client_types.MfaConfigSendCodeResponse mfa_config_send_code = 25; defguard.client_types.ClientMfaFlowStartResponse client_mfa_flow_start = 26; defguard.client_types.ClientMfaFlowStepStartResponse client_mfa_flow_step_start = 27; + defguard.client_types.ClientMfaFlowStepFinishResponse client_mfa_flow_step_finish = 28; + defguard.client_types.ClientMfaFlowRemoteResponse await_flow_finish = 29; } } @@ -222,6 +224,9 @@ message CoreRequest { defguard.client_types.MfaConfigSendCodeRequest mfa_config_send_code = 26; defguard.client_types.ClientMfaFlowStartRequest client_mfa_flow_start = 28; defguard.client_types.ClientMfaFlowStepStartRequest client_mfa_flow_step_start = 29; + defguard.client_types.ClientMfaFlowStepFinishRequest client_mfa_flow_step_finish = 30; + defguard.client_types.ClientMfaFlowRemoteRequest await_flow_finish = 31; + defguard.client_types.ClientMfaFlowApproveRequest client_mfa_flow_approve = 32; } } From f71a57a1c90b2a49a8b5b3c4520c3eb02b03eac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Mon, 21 Sep 2026 21:33:55 +0200 Subject: [PATCH 3/5] adjust field naming --- v2/proxy.proto | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v2/proxy.proto b/v2/proxy.proto index 76842ea..269fb22 100644 --- a/v2/proxy.proto +++ b/v2/proxy.proto @@ -120,7 +120,7 @@ message CoreResponse { defguard.client_types.ClientMfaFlowStartResponse client_mfa_flow_start = 26; defguard.client_types.ClientMfaFlowStepStartResponse client_mfa_flow_step_start = 27; defguard.client_types.ClientMfaFlowStepFinishResponse client_mfa_flow_step_finish = 28; - defguard.client_types.ClientMfaFlowRemoteResponse await_flow_finish = 29; + defguard.client_types.ClientMfaFlowRemoteResponse await_flow_step_finish = 29; } } @@ -225,7 +225,7 @@ message CoreRequest { defguard.client_types.ClientMfaFlowStartRequest client_mfa_flow_start = 28; defguard.client_types.ClientMfaFlowStepStartRequest client_mfa_flow_step_start = 29; defguard.client_types.ClientMfaFlowStepFinishRequest client_mfa_flow_step_finish = 30; - defguard.client_types.ClientMfaFlowRemoteRequest await_flow_finish = 31; + defguard.client_types.ClientMfaFlowRemoteRequest await_flow_step_finish = 31; defguard.client_types.ClientMfaFlowApproveRequest client_mfa_flow_approve = 32; } } From 83da36b380f8d843ef4983c24b98e47c84a4dae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Tue, 22 Sep 2026 10:33:06 +0200 Subject: [PATCH 4/5] adjust naming for flow-related messages --- common/client_types.proto | 18 +++++++++--------- v2/proxy.proto | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/common/client_types.proto b/common/client_types.proto index c7a83e5..669fd59 100644 --- a/common/client_types.proto +++ b/common/client_types.proto @@ -308,26 +308,26 @@ message MfaStepResult { } } -message ClientMfaFlowStartRequest { +message MfaFlowStartRequest { int64 location_id = 1; string pubkey = 2; optional defguard.enterprise.posture.v2.DevicePostureData posture_data = 3; repeated MfaMethod selected_methods = 4; } -message ClientMfaFlowStartResponse { +message MfaFlowStartResponse { oneof outcome { MfaFlowStartAccepted accepted = 1; MfaFlowStartRejected rejected = 2; } } -message ClientMfaFlowStepStartRequest { +message MfaFlowStepStartRequest { string token = 1; MfaMethod method = 2; } -message ClientMfaFlowStepStartResponse { +message MfaFlowStepStartResponse { MfaStepStarted started = 1; } @@ -349,7 +349,7 @@ message MfaFido2Assertion { // The session's persisted method selects the verifier. An unset submission is // valid only for OIDC and MobileApprove polling. -message ClientMfaFlowStepFinishRequest { +message MfaFlowStepFinishRequest { string token = 1; string step_attempt_id = 2; oneof submission { @@ -359,16 +359,16 @@ message ClientMfaFlowStepFinishRequest { } } -message ClientMfaFlowStepFinishResponse { +message MfaFlowStepFinishResponse { MfaStepResult result = 1; } -message ClientMfaFlowRemoteRequest { +message MfaFlowRemoteRequest { string token = 1; string step_attempt_id = 2; } -message ClientMfaFlowRemoteResponse { +message MfaFlowRemoteResponse { MfaStepResult result = 1; } @@ -377,7 +377,7 @@ message MfaMobileApprovalProof { string auth_pub_key = 2; } -message ClientMfaFlowApproveRequest { +message MfaFlowApproveRequest { string token = 1; string step_attempt_id = 2; MfaMobileApprovalProof proof = 3; diff --git a/v2/proxy.proto b/v2/proxy.proto index 269fb22..500e681 100644 --- a/v2/proxy.proto +++ b/v2/proxy.proto @@ -117,10 +117,10 @@ message CoreResponse { defguard.client_types.MfaConfigStartResponse mfa_config_start = 23; defguard.client_types.MfaConfigAuthorizeResponse mfa_config_authorize = 24; defguard.client_types.MfaConfigSendCodeResponse mfa_config_send_code = 25; - defguard.client_types.ClientMfaFlowStartResponse client_mfa_flow_start = 26; - defguard.client_types.ClientMfaFlowStepStartResponse client_mfa_flow_step_start = 27; - defguard.client_types.ClientMfaFlowStepFinishResponse client_mfa_flow_step_finish = 28; - defguard.client_types.ClientMfaFlowRemoteResponse await_flow_step_finish = 29; + defguard.client_types.MfaFlowStartResponse mfa_flow_start = 26; + defguard.client_types.MfaFlowStepStartResponse mfa_flow_step_start = 27; + defguard.client_types.MfaFlowStepFinishResponse mfa_flow_step_finish = 28; + defguard.client_types.MfaFlowRemoteResponse mfa_flow_remote = 29; } } @@ -222,11 +222,11 @@ message CoreRequest { defguard.client_types.MfaConfigStartRequest mfa_config_start = 24; defguard.client_types.MfaConfigAuthorizeRequest mfa_config_authorize = 25; defguard.client_types.MfaConfigSendCodeRequest mfa_config_send_code = 26; - defguard.client_types.ClientMfaFlowStartRequest client_mfa_flow_start = 28; - defguard.client_types.ClientMfaFlowStepStartRequest client_mfa_flow_step_start = 29; - defguard.client_types.ClientMfaFlowStepFinishRequest client_mfa_flow_step_finish = 30; - defguard.client_types.ClientMfaFlowRemoteRequest await_flow_step_finish = 31; - defguard.client_types.ClientMfaFlowApproveRequest client_mfa_flow_approve = 32; + defguard.client_types.MfaFlowStartRequest mfa_flow_start = 28; + defguard.client_types.MfaFlowStepStartRequest mfa_flow_step_start = 29; + defguard.client_types.MfaFlowStepFinishRequest mfa_flow_step_finish = 30; + defguard.client_types.MfaFlowRemoteRequest mfa_flow_remote = 31; + defguard.client_types.MfaFlowApproveRequest mfa_flow_approve = 32; } } From 8df8c23b49d29349822280917dcdc4a2baf04d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20W=C3=B3jcik?= Date: Mon, 5 Oct 2026 11:00:15 +0200 Subject: [PATCH 5/5] restore version markers --- common/client_types.proto | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/common/client_types.proto b/common/client_types.proto index 77573ca..700606e 100644 --- a/common/client_types.proto +++ b/common/client_types.proto @@ -134,8 +134,9 @@ message DeviceConfig { // Omitted (along with the location) when incompatible. optional LocationMfaMode location_mfa_mode = 11 [deprecated = true]; optional ServiceLocationMode service_location_mode = 12; + // Added for 2.1 optional bool posture_check_required = 13; - // The ordered steps of the MFA flow resolved for this user at this + // [2.2] The ordered steps of the MFA flow resolved for this user at this // location. repeated MfaStep steps = 14; // [2.2] MTU for the client. @@ -159,11 +160,11 @@ message InstanceInfo { bool disable_all_traffic = 7 [deprecated = true]; optional string openid_display_name = 8; optional ClientTrafficPolicy client_traffic_policy = 9; - // When ANY enrolled instance has this true, the desktop + // [2.1] When ANY enrolled instance has this true, the desktop // client and CLI hide, block, and disconnect bare WireGuard tunnels // (OR-across-instances semantics). optional bool disable_tunnels = 10; - // Lightweight summary of the enrolled user's configured MFA methods. + // [2.2] Lightweight summary of the enrolled user's configured MFA methods. // Used for quick checks (e.g. "does this user have any MFA methods?"). MfaUserState mfa_user_state = 11; // [2.2] absent when this core cannot configure mfa from the client @@ -211,7 +212,7 @@ enum MfaMethod { FIDO2 = 5; } -// Multi-step MFA +// [2.2] Multi-step MFA message MfaStepMethod { MfaMethod method = 1; @@ -350,7 +351,7 @@ message MfaBiometricSignature { string signature = 1; } -// CTAP-native binary fields. Carries no clientDataJSON. +// CTAP-native binary fields. message MfaFido2Assertion { bytes rp_id_hash = 1; bytes authenticator_data = 2; @@ -400,7 +401,7 @@ message ClientMfaStartRequest { string pubkey = 2; // MfaMethod.TOTP is 0, so an omitted value and explicit TOTP are equivalent. MfaMethod method = 3; - // Required when the location has posture policies assigned. + // [2.1] Required when the location has posture policies assigned. optional defguard.enterprise.posture.v2.DevicePostureData posture_data = 4; } @@ -459,7 +460,7 @@ message CodeMfaSetupFinishResponse { repeated string recovery_codes = 1; } -// MFA factor configuration for an enrolled device. +// [2.2] MFA factor configuration for an enrolled device. // Authenticate with the device's polling token and public key. message MfaConfigStartRequest { string token = 1;