Skip to content

fix(mfa): match getAuthenticators by Authenticator.type field#998

Open
utkrishtsahu wants to merge 1 commit into
mainfrom
fix/mfa-getauthenticators-swift-parity
Open

fix(mfa): match getAuthenticators by Authenticator.type field#998
utkrishtsahu wants to merge 1 commit into
mainfrom
fix/mfa-getauthenticators-swift-parity

Conversation

@utkrishtsahu

@utkrishtsahu utkrishtsahu commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Changes

This change updates how MfaApiClient.getAuthenticators(factorsAllowed) filters the authenticators returned by the GET /mfa/authenticators endpoint.

What changed

  • Filtering logic — Authenticators are now filtered by comparing each Authenticator.type value directly against the factorsAllowed list using exact (case-sensitive) equality. Previously the SDK derived an "effective type" by inspecting oob_channel and authenticator_type (with aliasing, e.g. sms/phone, otp/totp, and treating oob as a wildcard). That derivation and its helpers have been removed.
  • Methods removed — the private helpers matchesFactorType(...) and getEffectiveType(...) in MfaApiClient.
  • No endpoint or public method signature changesgetAuthenticators(factorsAllowed: List<String>) keeps the same signature; only its internal filtering behavior changed.
  • DocumentationMfaApiClient KDoc and EXAMPLES.md updated so the factorsAllowed examples use the same factor values as the type field (e.g. phone, email, otp, recovery-code) instead of channel-level values like sms/oob.

Why it matters

The factorsAllowed values now map one-to-one to the Authenticator.type field, so filtering is predictable and matches the values a caller gets from MfaRequirements (MfaFactor.type). This is a behavioral change: callers passing channel-level or wildcard values such as sms or oob will no longer match — they should pass the resolved type value (e.g. phone).

Usage

// factorsAllowed values map directly to Authenticator.type
val factorTypes = requirements?.challenge?.map { it.type } ?: emptyList()

mfaClient
    .getAuthenticators(factorsAllowed = factorTypes) // e.g. ["otp", "phone", "email", "recovery-code"]
    .start(object : Callback<List<Authenticator>, MfaListAuthenticatorsException> {
        override fun onSuccess(result: List<Authenticator>) {
            // Only authenticators whose `type` matches one of factorsAllowed are returned
        }
        override fun onFailure(error: MfaListAuthenticatorsException) { }
    })

References

Testing

The getAuthenticators unit tests in MfaApiClientTest were updated/verified to exercise the exact-type matching: fixtures include a top-level type field and assert that only authenticators whose type is in factorsAllowed are returned. One fixture (shouldGetAuthenticatorsWithCallback) was updated to include the type field so it reflects a realistic response.

  • This change adds unit test coverage

  • This change adds integration test coverage

  • This change has been tested on the latest version of the platform/language or why not

Checklist

Summary by CodeRabbit

  • Documentation

    • Updated MFA examples to show the latest enrollment and challenge factor types.
    • Clarified which factor values are accepted when listing authenticators.
  • Bug Fixes

    • Improved authenticator filtering so only exact factor matches are returned, making MFA factor selection more predictable.

@utkrishtsahu utkrishtsahu requested a review from a team as a code owner July 1, 2026 10:26
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Authenticator filtering in MfaApiClient was changed from alias/effective-type matching (e.g., sms/phone, otp/totp) to exact case-sensitive equality against the authenticator's type field. Documentation and examples were updated accordingly, and a test mock was updated to include the type field.

Changes

Authenticator Filtering Update

Layer / File(s) Summary
Exact-match filtering logic and docs
auth0/src/main/java/com/auth0/android/authentication/mfa/MfaApiClient.kt
Filtering logic changed to factorsAllowed.contains(authenticator.type), removing prior alias-based matching helpers; KDoc for getAuthenticators and createFilteringAuthenticatorsAdapter updated with new examples and case-sensitive matching description.
Test and doc examples reflecting type field
auth0/src/test/java/com/auth0/android/authentication/MfaApiClientTest.kt, EXAMPLES.md
Test mock JSON now includes the type attribute; EXAMPLES.md callback and coroutines MFA examples updated to show phone instead of sms for enrollment and challenge factor types.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant MfaApiClient
  participant FilteringAdapter

  Caller->>MfaApiClient: getAuthenticators(factorsAllowed)
  MfaApiClient->>FilteringAdapter: createFilteringAuthenticatorsAdapter(factorsAllowed)
  FilteringAdapter->>FilteringAdapter: filter authenticator where factorsAllowed.contains(type)
  FilteringAdapter-->>MfaApiClient: filtered authenticators
  MfaApiClient-->>Caller: return result
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: filtering getAuthenticators by Authenticator.type.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/mfa-getauthenticators-swift-parity

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
auth0/src/main/java/com/auth0/android/authentication/mfa/MfaApiClient.kt (1)

305-319: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Same "phone" vs "oob" concern applies to this doc block.

This restates the exact-match filtering contract using factorsAllowed = ["phone", "email", "otp"] as an example. Same concern as the public KDoc above — please confirm this matches the real Authenticator.type values returned by GET /mfa/authenticators.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@auth0/src/main/java/com/auth0/android/authentication/mfa/MfaApiClient.kt`
around lines 305 - 319, The KDoc for the JSON adapter in MfaApiClient still uses
examples that may not match the real Authenticator.type values returned by GET
/mfa/authenticators. Update the doc block to use only documented/verified
factor-type examples and make the exact-match filtering contract consistent with
the actual API response values; locate the affected text in the adapter
documentation near the filtering description.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@auth0/src/main/java/com/auth0/android/authentication/mfa/MfaApiClient.kt`:
- Around line 127-140: The KDoc example in MfaApiClient.getAuthenticators uses
outdated factor values that won’t match SMS/email authenticators. Update the
sample callback and the `@param` factorsAllowed examples to use "oob" instead of
"phone" and "email", keeping the exact-match filtering note aligned with
Authenticator.type.

---

Duplicate comments:
In `@auth0/src/main/java/com/auth0/android/authentication/mfa/MfaApiClient.kt`:
- Around line 305-319: The KDoc for the JSON adapter in MfaApiClient still uses
examples that may not match the real Authenticator.type values returned by GET
/mfa/authenticators. Update the doc block to use only documented/verified
factor-type examples and make the exact-match filtering contract consistent with
the actual API response values; locate the affected text in the adapter
documentation near the filtering description.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 653affda-cf64-4839-b7ef-2ed4fdc1f553

📥 Commits

Reviewing files that changed from the base of the PR and between aa6581c and d727283.

📒 Files selected for processing (3)
  • EXAMPLES.md
  • auth0/src/main/java/com/auth0/android/authentication/mfa/MfaApiClient.kt
  • auth0/src/test/java/com/auth0/android/authentication/MfaApiClientTest.kt

Comment on lines +127 to 140
* mfaClient.getAuthenticators(listOf("otp", "phone"))
* .start(object : Callback<List<Authenticator>, MfaListAuthenticatorsException> {
* override fun onSuccess(result: List<Authenticator>) {
* // Only OTP and OOB authenticators returned
* // Only authenticators whose `type` is "otp" or "phone" are returned
* }
* override fun onFailure(error: MfaListAuthenticatorsException) { }
* })
* ```
*
* @param factorsAllowed Array of factor types to filter the authenticators (e.g., `["otp", "oob", "recovery-code"]`).
* Filtering matches each authenticator's [Authenticator.type] field against the
* provided values using exact (case-sensitive) equality.
*
* @param factorsAllowed Array of factor types to filter the authenticators (e.g., `["otp", "phone", "email", "recovery-code"]`).
* Must contain at least one factor type.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

What is the actual type field value returned by Auth0's GET /mfa/authenticators endpoint for a phone/SMS-based authenticator — "phone" or "oob"?

💡 Result:

For phone or SMS-based authenticators in Auth0, the actual field returned by the GET /mfa/authenticators endpoint is authenticator_type, and its value is "oob" [1][2]. While you may encounter the term "phone" in other parts of the Auth0 ecosystem—such as in configuration parameters, Management API requests, or MFA challenge requirement lists [3][4][5][2]—the specific authenticator_type field used to identify SMS or Voice factors within the list of enrolled authenticators is "oob" [1][2]. The specific transport method (e.g., SMS or Voice) is then provided in a separate field called oob_channel [1][2].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the relevant client and test references.
git ls-files 'auth0/src/main/java/com/auth0/android/authentication/mfa/MfaApiClient.kt' \
             'auth0/src/test/**/MfaApiClientTest.kt' \
             'auth0/src/**/MfaApiClientTest.kt' \
             'auth0/src/**/mfa/**' | sed 's#^`#-` #'

printf '\n== MfaApiClient.kt excerpt ==\n'
sed -n '110,155p' auth0/src/main/java/com/auth0/android/authentication/mfa/MfaApiClient.kt

printf '\n== Search for factor/type values in tests ==\n'
rg -n '"type"\s*:\s*"(oob|otp|phone|email|recovery-code)"|factorsAllowed|Authenticator.type|oob_channel|authenticator_type' auth0/src/test auth0/src/main -g '*MfaApiClientTest.kt' -g '*.kt'

Repository: auth0/Auth0.Android

Length of output: 8536


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the specific test regions mentioned by the review comment.
test_file=$(git ls-files 'auth0/src/test/**/MfaApiClientTest.kt' 'auth0/src/**/MfaApiClientTest.kt' | head -n 1)
if [ -z "$test_file" ]; then
  echo "MfaApiClientTest.kt not found"
  exit 0
fi

printf 'Using test file: %s\n' "$test_file"

for range in '240,270' '296,330' '340,390' '830,860'; do
  printf '\n== %s lines %s ==\n' "$test_file" "$range"
  sed -n "${range}p" "$test_file"
done

Repository: auth0/Auth0.Android

Length of output: 6455


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the surrounding code and nearby tests that define the expected factor values.
printf '\n== MfaApiClient.kt around the documented example ==\n'
sed -n '120,145p' auth0/src/main/java/com/auth0/android/authentication/mfa/MfaApiClient.kt

printf '\n== Search for API/model docs and test fixtures mentioning MFA authenticator types ==\n'
rg -n 'oob|otp|phone|email|recovery-code|authenticator_type|Authenticator.type|getAuthenticators' auth0/src/main/java auth0/src/test -g '*.kt'

Repository: auth0/Auth0.Android

Length of output: 50377


Use oob here instead of phone/email
GET /mfa/authenticators returns Authenticator.type == "oob" for SMS/email authenticators, so the example currently suggests filter values that won’t match those items. Update the KDoc sample and factorsAllowed examples to use oob.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@auth0/src/main/java/com/auth0/android/authentication/mfa/MfaApiClient.kt`
around lines 127 - 140, The KDoc example in MfaApiClient.getAuthenticators uses
outdated factor values that won’t match SMS/email authenticators. Update the
sample callback and the `@param` factorsAllowed examples to use "oob" instead of
"phone" and "email", keeping the exact-match filtering note aligned with
Authenticator.type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants