此内容正在翻译中,完成后将会在此处提供。
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:
{
"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 Type | Platform | Verification Method |
| Native Android app | Android | Digital Asset Links |
| Native iOS app | iOS | App Attest (future) |
| Web dApp | Any | Domain verification via reflector |
| PWA | Android | Trusted Web Activity links |
Digital Asset Links
For native Android apps, Digital Asset Links (DAL) is the primary verification method.
How It Works
The dApp includes a
uriin its identity:https://myapp.comThe wallet fetches
https://myapp.com/.well-known/assetlinks.jsonThis file declares which Android apps are associated with the domain
The wallet checks if the requesting app's signature matches
assetlinks.json Format
[{
"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
+---------+ +---------+ +------------------+
| 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:
# 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:
Go to Google Play Console → Your App → Release → Setup → App Signing
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:
The key was generated in a genuine Android device
The app's package name and signature
Device security state
MWA Attestation Flow
The spec defines error code -100 (ERROR_ATTEST_ORIGIN_ANDROID) for attestation failures:
{
"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
The dApp runs on
https://mywebapp.comIt connects to a reflector that verifies the origin
The reflector attests to the wallet that the connection came from the claimed domain
The wallet can fetch the site's favicon and metadata
Trusted Reflector Concept
The reflector serves as an identity authority for web origins:
+---------------+ +------------+ +----------+
| 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
+------------------------------------+
| [check] Verified: Magic Eden |
| magiceden.io |
| |
| This app's identity has been |
| cryptographically verified. |
| |
| [Accounts to authorize] |
| |
| [Approve] [Decline] |
+------------------------------------+Unverified dApp
+------------------------------------+
| [!] 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
[{
"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/jsonNo redirects (200 OK directly)
Accessible without authentication
3. Configure Your dApp
Pass the matching URI in authorize:
await wallet.authorize({
identity: {
uri: 'https://yourdomain.com',
name: 'Your App Name',
icon: 'icon.png'
}
});4. Test Verification
Use the Digital Asset Links tester:
https://developers.google.com/digital-asset-links/tools/generatorOr verify manually:
curl -I https://yourdomain.com/.well-known/assetlinks.json
# Should return 200 OK with application/jsonMultiple Fingerprints
You may need multiple fingerprints for:
Debug vs release builds
Different signing keys
Google Play signing vs local signing
[{
"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:
| Field | Type | Required | Description |
uri | string | Yes | Base URI for verification |
icon | string | No | Relative path to icon |
name | string | No | Display name |
Icon Resolution
The icon path is relative to the URI:
URI:
https://myapp.comIcon:
assets/icon.pngFull 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
uriShow "Unknown dApp"
Fetch metadata from the URI
Security Considerations
Trust Model
Identity verification assumes:
The domain owner controls the assetlinks.json file
The app signature matches the declared fingerprint
DNS is not compromised (HTTPS certificates help)
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.jsonEnsure HTTPS is working
No redirects
"Verification failed: package name mismatch"
The
package_namein assetlinks.json must exactly match your app's packageCheck 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:
Use a local server with ngrok or similar
Configure assetlinks.json on the tunnel URL
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
Always configure DAL: Even for simple apps. It builds user trust.
Use your main domain: Don't use obscure subdomains for
identity.uri.Keep assetlinks.json updated: When rotating keys, update the file before deploying new builds.
Include meaningful names: Help users identify your app in the wallet UI.
Provide clear icons: 512x512 PNG with transparent background works well.
For Wallet Developers
Always verify when possible: Default to requiring verification for production apps.
Clearly indicate verification status: Users should know if an app is verified.
Cache wisely: Balance security (frequent checks) with performance (caching).
Fail open for debugging: Allow unverified connections in development mode.
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.