Mobile
MWA Deep Dive

MWA Deep Dive

Dieser Inhalt wird übersetzt und wird hier verfügbar sein, sobald er fertig ist.

Identity Verification

When a wallet shows "My dApp wants to connect," how does it know the request actually came from "My dApp"? The MWA spec defines identity verification mechanisms that let wallets authenticate dApps, protecting users from phishing and impersonation.

The Identity Problem

Without verification, any app could claim to be any other:

json
{
  "method": "authorize",
  "params": {
    "identity": {
      "name": "Phantom Wallet",
      "uri": "https://phantom.app"
    }
  }
}

The user sees "Phantom Wallet" and approves, but the request came from a malicious app.

Identity verification solves this by cryptographically linking the dApp's claimed identity to something verifiable.

Verification Mechanisms

MWA supports different verification mechanisms depending on the platform and dApp type:

dApp TypePlatformVerification Method
Native Android appAndroidDigital Asset Links
Native iOS appiOSApp Attest (future)
Web dAppAnyDomain verification via reflector
PWAAndroidTrusted Web Activity links

Digital Asset Links

For native Android apps, Digital Asset Links (DAL) is the primary verification method.

How It Works

  1. The dApp includes a uri in its identity: https://myapp.com

  2. The wallet fetches https://myapp.com/.well-known/assetlinks.json

  3. This file declares which Android apps are associated with the domain

  4. The wallet checks if the requesting app's signature matches

assetlinks.json Format

json
[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example.myapp",
    "sha256_cert_fingerprints": [
      "14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"
    ]
  }
}]

Verification Flow

text
+---------+      +---------+      +------------------+
|  dApp   |      | Wallet  |      | myapp.com server |
+----+----+      +----+----+      +--------+---------+
     |                |                    |
     | authorize      |                    |
     | uri: myapp.com |                    |
     |--------------->|                    |
     |                |                    |
     |                | GET /.well-known/  |
     |                | assetlinks.json    |
     |                |------------------->|
     |                |                    |
     |                |<-------------------|
     |                | [{ package, sig }] |
     |                |                    |
     |                | Check: request from|
     |                | com.example.myapp  |
     |                | with matching sig? |
     |                |                    |
     |<---------------|                    |
     | Verified!      |                    |

Fingerprint Calculation

The SHA-256 fingerprint is derived from the app's signing certificate:

shellscript
# Get fingerprint from your keystore
keytool -list -v -keystore my-release-key.keystore -alias my-key-alias
# Output includes: SHA256: 14:6D:E9:83:C5:73:...

For apps signed by Google Play:

  1. Go to Google Play Console → Your App → Release → Setup → App Signing

  2. Copy the SHA-256 fingerprint from "App signing key certificate"

Android Attestation

Beyond DAL, Android provides hardware-backed attestation through the Key Attestation API and SafetyNet/Play Integrity.

Key Attestation

The dApp can generate a key in hardware (TEE/Strongbox) with an attestation certificate chain. The wallet can verify:

  1. The key was generated in a genuine Android device

  2. The app's package name and signature

  3. Device security state

MWA Attestation Flow

The spec defines error code -100 (ERROR_ATTEST_ORIGIN_ANDROID) for attestation failures:

json
{
  "error": {
    "code": -100,
    "message": "Origin attestation failed",
    "data": {
      "attestation_type": "android",
      "reason": "signature_mismatch"
    }
  }
}

Wallets may require attestation for:

  • High-value transactions

  • Sensitive operations

  • Apps without DAL configured

Web dApp Verification

Web dApps connecting via reflector use domain-based verification.

How It Works

  1. The dApp runs on https://mywebapp.com

  2. It connects to a reflector that verifies the origin

  3. The reflector attests to the wallet that the connection came from the claimed domain

  4. The wallet can fetch the site's favicon and metadata

Trusted Reflector Concept

The reflector serves as an identity authority for web origins:

text
+---------------+     +------------+     +----------+
| Web dApp      |---->| Reflector  |<----| Wallet   |
| mywebapp.com  |     |            |     |          |
+---------------+     | Verifies   |     | Trusts   |
                      | origin     |     | reflector|
                      +------------+     +----------+

The wallet must trust the reflector. A malicious reflector could lie about origins.

CORS and Origin Headers

When a web page connects to the reflector, the browser includes Origin and Referer headers. The reflector can verify these match the claimed identity.

Verification UI in Wallets

Wallets display verification status to users:

Verified dApp

text
+------------------------------------+
|  [check] Verified: Magic Eden      |
|  magiceden.io                      |
|                                    |
|  This app's identity has been      |
|  cryptographically verified.       |
|                                    |
|  [Accounts to authorize]           |
|                                    |
|  [Approve]         [Decline]       |
+------------------------------------+

Unverified dApp

text
+------------------------------------+
|  [!] Unverified: Some dApp         |
|  claims: example.com               |
|                                    |
|  This app's identity could not     |
|  be verified. Proceed with caution.|
|                                    |
|  [Accounts to authorize]           |
|                                    |
|  [Approve Anyway]    [Decline]     |
+------------------------------------+

Some wallets may refuse unverified connections entirely.

Setting Up DAL for Your dApp

Step-by-step guide:

1. Create assetlinks.json

json
[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.yourcompany.yourapp",
    "sha256_cert_fingerprints": [
      "YOUR_SHA256_FINGERPRINT"
    ]
  }
}]

2. Host the File

Place at https://yourdomain.com/.well-known/assetlinks.json

Requirements:

  • HTTPS (not HTTP)

  • Content-Type: application/json

  • No redirects (200 OK directly)

  • Accessible without authentication

3. Configure Your dApp

Pass the matching URI in authorize:

typescript
await wallet.authorize({
  identity: {
    uri: 'https://yourdomain.com',
    name: 'Your App Name',
    icon: 'icon.png'
  }
});

4. Test Verification

Use the Digital Asset Links tester:

text
https://developers.google.com/digital-asset-links/tools/generator

Or verify manually:

shellscript
curl -I https://yourdomain.com/.well-known/assetlinks.json
# Should return 200 OK with application/json

Multiple Fingerprints

You may need multiple fingerprints for:

  • Debug vs release builds

  • Different signing keys

  • Google Play signing vs local signing

json
[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.yourcompany.yourapp",
    "sha256_cert_fingerprints": [
      "DEBUG_FINGERPRINT",
      "RELEASE_FINGERPRINT",
      "GOOGLE_PLAY_FINGERPRINT"
    ]
  }
}]

Identity Object Fields

The identity parameter in authorize:

FieldTypeRequiredDescription
uristringYesBase URI for verification
iconstringNoRelative path to icon
namestringNoDisplay name

Icon Resolution

The icon path is relative to the URI:

  • URI: https://myapp.com

  • Icon: assets/icon.png

  • Full URL: https://myapp.com/assets/icon.png

The wallet fetches and displays this icon in authorization UI.

Name Display

If name is omitted, the wallet may:

  • Use the domain from uri

  • Show "Unknown dApp"

  • Fetch metadata from the URI

Security Considerations

Trust Model

Identity verification assumes:

  1. The domain owner controls the assetlinks.json file

  2. The app signature matches the declared fingerprint

  3. DNS is not compromised (HTTPS certificates help)

  4. The device isn't rooted/compromised

Limitations

DAL doesn't prove:

  • The app does what it claims

  • The domain is legitimate (phishing domains can have DAL too)

  • The app isn't malicious despite being "verified"

Users should still exercise judgment.

Time-of-Check vs Time-of-Use

The wallet verifies identity when authorize is called. But:

  • The dApp could change behavior afterward

  • The assetlinks.json could be modified

For high-security scenarios, wallets may re-verify periodically.

Debugging Verification

Common Issues

"Verification failed: assetlinks.json not found"

  • Check file is at /.well-known/assetlinks.json

  • Ensure HTTPS is working

  • No redirects

"Verification failed: package name mismatch"

  • The package_name in assetlinks.json must exactly match your app's package

  • Check for typos

"Verification failed: fingerprint mismatch"

  • Ensure you're using the correct signing key

  • For Play Store apps, use the Play Signing fingerprint

  • Regenerate fingerprint if keys changed

"Verification failed: network error"

  • The wallet couldn't reach your server

  • Check server availability

  • Some wallets cache results; try clearing cache

Testing Without Production Server

For development:

  1. Use a local server with ngrok or similar

  2. Configure assetlinks.json on the tunnel URL

  3. Use that URL in your dApp's identity

Future Verification Methods

The spec allows for future methods:

iOS App Attest

Apple's DeviceCheck and App Attest APIs could provide similar guarantees for iOS apps.

Decentralized Identity

Future versions might support:

  • ENS or SNS domain verification

  • On-chain identity registries

  • Decentralized attestation services

Passkey Integration

WebAuthn/Passkeys could link wallet authorization to device biometrics and hardware keys.

Best Practices

For dApp Developers

  1. Always configure DAL: Even for simple apps. It builds user trust.

  2. Use your main domain: Don't use obscure subdomains for identity.uri.

  3. Keep assetlinks.json updated: When rotating keys, update the file before deploying new builds.

  4. Include meaningful names: Help users identify your app in the wallet UI.

  5. Provide clear icons: 512x512 PNG with transparent background works well.

For Wallet Developers

  1. Always verify when possible: Default to requiring verification for production apps.

  2. Clearly indicate verification status: Users should know if an app is verified.

  3. Cache wisely: Balance security (frequent checks) with performance (caching).

  4. Fail open for debugging: Allow unverified connections in development mode.

  5. Log verification failures: Help developers diagnose issues.

In the next lesson, we examine the reflector protocol in detail and explore debugging techniques for MWA sessions.

Blueshift © 2026Commit: 1b8118f