0

I'm building a demo android app (technically flutter but this code is in the native java code).

The purpose of app is to demonstrate logging into an app using fido.

My problem is during the fido registration process. It is returning the error:

SECURITY_ERR The incoming request cannot be validated

I'm trying to test the app completely on my local system.

To this end I've created a /etc/hosts entry for the domain 'squarephone.biz' which points to 10.0.2.2.

The android/flutter app is able to connect to my local fido server.

The local fido server hosts the assetslinks.json file.

I'm guessing the problem is around the app not accessing the assetslinks.json file as I don't see any request for that file.

You can see the fido-client here: https://github.com/onepub-dev/fido-client

The client is using a third party plug where all the fido interaction takes place:

https://github.com/onepub-dev/contrib-fido2-flutter-lib

The Android directory is where all of the interesting pieces lie.

My current guess is either you can't test using a local fido server (but the local /etc/hosts should get around this) or that one of my configure files are incorrect.

This is the call that is failing:

The key params are:

rpDomain: squarephone.biz

coseAlgoValue: -7

 private fun initiateRegistration(
        result: Result, challenge: String, userId: String, username: String,
        rpDomain: String, rpName: String, coseAlgoValue: List<Int>, excludeCredentials: List<String>
    ) {
        val rpEntity = PublicKeyCredentialRpEntity(rpDomain, rpName, null)
        val options = PublicKeyCredentialCreationOptions.Builder()
            .setRp(rpEntity)
            .setUser(
                PublicKeyCredentialUserEntity(
                    userId.to(),
                    userId,
                    null,
                    username
                )
            )
            .setChallenge(challenge.decodeBase64())
            .setParameters(
                coseAlgoValue.map {
                    PublicKeyCredentialParameters(
                        PublicKeyCredentialType.PUBLIC_KEY.toString(),
                        it
                    )
                }
            )
            .setExcludeList(
                excludeCredentials.map {
                    PublicKeyCredentialDescriptor(
                        PublicKeyCredentialType.PUBLIC_KEY.toString(),
                        it.decodeBase64(),
                        null
                    )
                }
            )
            .setAuthenticatorSelection(
                AuthenticatorSelectionCriteria.Builder().setAttachment(Attachment.PLATFORM).build()
            )
            .build()

        val fidoClient = Fido.getFido2ApiClient(activity)
        val registerIntent = fidoClient.getRegisterPendingIntent(options)
        registerIntent.addOnFailureListener {
            val errCode = "FAILED_TO_GET_REGISTER_INTENT"
            result.error(errCode, it.message, null);
        }
        registerIntent.addOnSuccessListener { pendingIntent ->
            if (pendingIntent != null) {
                // Start a FIDO2 registration request.
                activity?.startIntentSenderForResult(
                    pendingIntent.intentSender,
                    REGISTER_REQUEST_CODE,
                    null,
                    0,
                    0,
                    0
                )
            } else {
                val errCode = "FAILED_TO_GET_REGISTER_INTENT"
                result.error(errCode, "An error occurred", null);
            }
        }
    }

The problem is that I can't see any way to get any diagnostic information out of android. I'm really looking for a log of what android is doing and what is failing.

Here are the key files:

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="dev.onepub.fido.client">
   <application
        android:label="fido_client"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
        <!-- required by FIDO links to res/values/strings.xml-->
        <meta-data android:name="asset_statements" android:resource="@string/asset_statements" />
    </application>
</manifest>

strings.xml

<resources>
        <string name="asset_statements" translatable="false">
    [{
            \"include\": \"http://squarephone.biz:8080/.well-known/assetlinks.json\"
    }]
        </string>
</resources>

I've included the assetlinks.json file but it's not playing a part as its not being accessed from the server.

assetlinks.json

[
    {
      "relation" : [
        "delegate_permission/common.handle_all_urls",
        "delegate_permission/common.get_login_creds"
      ],
      "target" : {
        "namespace" : "web",
        "site" : "http://squarephone.biz:8080"
      }
    },
    {
      "relation" : [
        "delegate_permission/common.handle_all_urls",
        "delegate_permission/common.get_login_creds"
      ],
      "target" : {
        "namespace" : "android_app",
        "package_name" : "dev.onepub.fido.client",
        "sha256_cert_fingerprints" : [
           "XXXX:XXXX"
        ]
      }
    }
  ]

Here is a link to the fido server, however, I don't believe that it plays a part in the problem.

https://github.com/onepub-dev/fido-server

Brett Sutton
  • 3,900
  • 2
  • 28
  • 53

1 Answers1

0

So eventually found the problem.

The assetlinks.json file MUST be hosted on a public web server accessible to Google's servers.

During the auth process your phone sends a request to Google to validate the asset.

The Google server fetches the assetslinks.json file from the asset_statement in the strings.xml file.

If the google servers can't fetch the file you get the above-noted error:

SECURITY_ERR The incoming request cannot be validated

Brett Sutton
  • 3,900
  • 2
  • 28
  • 53