Skip to content

Okta Auth: Only One Push Factor Contacted for MFA, No Status Validation #31759

Description

@stk0vrfl0w

Describe the bug

The Okta authentication backend has two critical issues when handling MFA push notifications:

  1. Only one push factor receives notifications: When a user has multiple registered Okta Verify Push devices, only the last one encountered during factor enumeration receives the push notification. Other registered push devices are ignored, even if they are active and available.

  2. No factor status validation: The code does not check whether a factor's status is ACTIVE before attempting to use it. If the selected factor is suspended, inactive, or pending activation, authentication will fail even though the user may have other active factors available.

These issues stem from the factor selection logic in backend.go:

  • The loop overwrites pushFactor on each iteration rather than collecting all push factors
  • The mfaFactor struct lacks a Status field to validate factor state
  • Only one selectedFactor is chosen and verified

To Reproduce

Steps to reproduce the behavior:

  1. Configure Okta auth backend in Vault:
vault auth enable okta
vault write auth/okta/config \
    org_name="your-org" \
    api_token="your-token"
  1. In Okta, register a user with multiple Okta Verify Push devices (e.g., mobile phone and tablet)

  2. Attempt to authenticate via Vault:

vault login -method=okta username=testuser
# Enter password when prompted
  1. Observe that only one device receives the push notification (depending on API response order)

Alternative reproduction (suspended factor):

  1. Register a user with multiple push factors
  2. Suspend one of the factors in Okta admin console
  3. If the suspended factor happens to be selected, authentication fails despite having active factors

Expected behavior

Option 1 (Ideal): All active push factors should receive notifications simultaneously, and authentication should succeed when any one is approved. This provides the best user experience and redundancy.

Option 2 (Minimum):

  • Only select factors with status: "ACTIVE"
  • If multiple active push factors exist, clearly document which one will be used (first, last, etc.)
  • Provide a way for users to specify their preferred factor

Environment:

  • Vault Server Version: (affects all versions with Okta auth)
  • Vault CLI Version: (all versions)
  • Server Operating System/Architecture: (all platforms)

Additional context

Code Analysis

The mfaFactor struct does not include the status field from Okta's API response:

type mfaFactor struct {
    Id       string `json:"id"`
    Type     string `json:"factorType"`
    Provider string `json:"provider"`
    // Missing: Status string `json:"status"`
    Embedded struct {
        Challenge struct {
            CorrectAnswer *int `json:"correctAnswer"`
        } `json:"challenge"`
    } `json:"_embedded"`
}

The factor selection loop only retains one push factor:

for _, v := range result.Embedded.Factors {
    // ...
    switch v.Type {
    case mfaTOTPMethod:
        totpFactor = &v
    case mfaPushMethod:
        pushFactor = &v  // Overwrites previous push factors!
    }
}

Security & Usability Impact

  • Reduced redundancy: Users cannot rely on backup devices if their primary device is unavailable
  • Silent failures: No indication to user why a specific device was chosen or if others exist
  • Suspended factor risk: Authentication fails unnecessarily when an inactive factor is selected while active factors are available
  • Poor UX: Users with multiple devices cannot predict which will receive the push

Test Coverage Gap

The test file backend_test.go explicitly states: "This test does not exercise MFA however (which is an enterprise feature)" - there is zero test coverage for:

  • Multiple push factors
  • Factor status validation
  • MFA push notification flows
  • Factor selection logic

Recommended Fix

  1. Add Status field to mfaFactor struct
  2. Filter factors to only include status == "ACTIVE"
  3. Collect all active push factors (not just one)
  4. Either:
    • Send push to all active factors and accept first approval (preferred), OR
    • Provide a mechanism for users to select their preferred factor
  5. Add comprehensive test coverage for MFA scenarios

Metadata

Metadata

Assignees

No one assigned

    Labels

    auth/oktabugUsed to indicate a potential bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions