# App Links are properly configured for Android

- **Pattern:** `ab-001860` (`mobile-navigation-linking.deep-linking.app-links-android`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001860
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001860)

## Why it matters

Without `assetlinks.json` published at `/.well-known/assetlinks.json` on your domain, Android cannot cryptographically verify that your app owns the domain, so the OS falls back to showing an app-chooser dialog (or opens the browser) every time a user taps an HTTPS link. This breaks email confirmation flows, referral links, and payment redirects — all of which depend on landing users directly in the app. The Android App Links spec (android-app-links) mandates both the JSON file and intent filter configuration; missing either half means app link verification fails silently in production.

## Severity rationale

High because missing assetlinks.json causes Android to skip app-link verification entirely, routing users to a browser or app-chooser on every HTTPS deep link instead of directly into the app.

## Remediation

Serve `assetlinks.json` at `https://<your-domain>/.well-known/assetlinks.json` with `Content-Type: application/json`. Get your SHA-256 fingerprint from your release keystore using `keytool -list -v -keystore release.keystore`.

```json
[
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "com.yourcompany.appname",
      "sha256_cert_fingerprints": [
        "AA:BB:CC:..."
      ]
    }
  }
]
```

For Expo-managed builds, add the intent filter to `app.json`:

```json
{
  "android": {
    "intentFilters": [
      {
        "action": "VIEW",
        "autoVerify": true,
        "data": [{ "scheme": "https", "host": "myapp.com" }],
        "category": ["BROWSABLE", "DEFAULT"]
      }
    ]
  }
}
```

`autoVerify: true` is required — without it, Android skips domain verification even if the file is present.

## Detection

- **ID:** `app-links-android`
- **Severity:** `high`
- **What to look for:** Check for `assetlinks.json` file. This file should exist in your `android/` directory or be served at `https://<your-domain>/.well-known/assetlinks.json` on your backend. The file should specify your app's package name and SHA-256 certificate fingerprint. For Expo-managed projects, check `app.json` for `android.intentFilters` config.
- **Pass criteria:** Count all intent filter entries in app.json or AndroidManifest.xml. Either an `assetlinks.json` file exists in the Android build, or `app.json` contains at least 1 intent filter with `autoVerify: true` and HTTPS data scheme. The file/config includes your app's package name and valid certificate info.
- **Fail criteria:** No `assetlinks.json` file or config found. Android app links are not configured.
- **Skip (N/A) when:** The app has no Android support (no `android` field in app.json), or app links are not required (custom scheme-only deep links are acceptable).
- **Cross-reference:** The App Store Readiness audit (`mobile-store-readiness`) checks Android build.gradle configuration that must align with app link intent filter setup.
- **Detail on fail:** `"No assetlinks.json file found in android/ directory"` or `"app.json has no android.intentFilters configuration for HTTPS deeplinks"`
- **Remediation:** Configure App Links for Android. Create `assetlinks.json` at `.well-known/assetlinks.json` on your domain (served via HTTPS):

  ```json
  [
    {
      "relation": ["delegate_permission/common.handle_all_urls"],
      "target": {
        "namespace": "android_app",
        "package_name": "com.yourcompany.appname",
        "sha256_cert_fingerprints": [
          "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88"
        ]
      }
    }
  ]
  ```

  Get your app's SHA-256 fingerprint from your keystore. Alternatively, in `app.json` for Expo:

  ```json
  {
    "android": {
      "intentFilters": [
        {
          "action": "VIEW",
          "data": [
            {
              "scheme": "https",
              "host": "myapp.com"
            }
          ],
          "category": ["BROWSABLE", "DEFAULT"]
        }
      ]
    }
  }
  ```

---

## External references

- external android-app-links — https://developer.android.com/training/app-links

Taxons: user-experience, operational-readiness

HTML version: https://auditbuffet.com/patterns/ab-001860
