-
Notifications
You must be signed in to change notification settings - Fork 73
feat: Origin identification proposal #91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 3 commits
e21a7b9
292c009
32ba332
b5f4002
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,12 @@ | ||
| 7 August 2025 - `Feature` Enhanced End-User Security in TonConnect: | ||
| - Added `/verify` endpoint for connection verification with statuses: `ok`, `danger`, `warning`, `unknown` | ||
| - Introduced encrypted `request_source` metadata in bridge messages containing origin, IP, User-Agent, timestamp, and client ID | ||
| - Added BridgeRequestSource struct for request source tracking and verification | ||
| - Updated bridge message format to include optional `request_source` field | ||
| - Enhanced wallet workflows with connection and transaction verification processes | ||
| - Added comprehensive wallet implementation guidelines for security features | ||
| - Implemented phased rollout approach for verification status responses | ||
| - Maintained full backward compatibility with existing dApps and bridges | ||
| - Added user interface guidelines for verification marks and security warnings | ||
|
|
||
| 7 March 2023 - `Feature` format of `DeviceInfo` of `ConnectEventSuccess` changed; Parameter `maxMessages` added to the Feature `SendTransaction`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -61,3 +61,106 @@ Multiple network accounts can be created for one key pair. Implement this functi | |
|
|
||
| We recommend wallets provide the ability to disconnect session with a specified dapp because the dapp may have an incomplete UI. | ||
|
|
||
| ## Security Verification | ||
|
|
||
| ### Connection Verification Implementation | ||
|
|
||
| 1) **Implement `/verify` endpoint integration** | ||
|
|
||
| For HTTP Bridge connections, wallets MUST implement connection verification: | ||
|
|
||
| - Extract origin and client_id from connection requests | ||
| - Send POST request to `${bridgeUrl}/verify` with connection details | ||
| - Process verification status and display appropriate UI to users | ||
|
|
||
| 2) **Verification Status Handling** | ||
|
|
||
| Wallets MUST handle all verification statuses appropriately: | ||
|
|
||
| - `ok` → Show that message is coming from the shown source, or show nothing | ||
| - `ok` + whitelisted domain → Show that message is coming from the shown source AND add source is verified | ||
| - `danger` → Show strong warning, recommend declining connection | ||
| - `warning` → Show caution message, let user decide | ||
| - `unknown` → Proceed without special indicators (default behavior) | ||
|
|
||
| 3) **Rollout Phase Awareness** | ||
|
|
||
| - **Phase 1 (first 6 months)**: Only `ok` and `unknown` statuses returned | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the one hand, this should be obvious, but still — why do we need to split the rollout into two phases? Why can’t we just show the statuses right away?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because we need time to update sdk on the dapps side, otherwise we don't have guarantees that client connects to the bridge before opening wallet. |
||
| - **Phase 2 (after 6 months)**: Full status set including `danger` and `warning` | ||
|
|
||
| ### Transaction Verification Implementation | ||
|
|
||
| 1) **Request Source Metadata Processing** | ||
|
|
||
| Wallets MUST implement transaction source verification: | ||
|
|
||
| - Decrypt `request_source` field from BridgeMessage using session private key | ||
| - Parse BridgeRequestSource JSON containing origin, IP, User-Agent, timestamp, client_id | ||
| - Obtain current IP address using bridge's `POST /myip` (can be cached) endpoint for comparison | ||
| - Compare metadata against current user information | ||
| - Display warnings for any mismatches | ||
|
|
||
| 2) **Mismatch Detection and Warnings** | ||
|
|
||
| Display appropriate warnings for detected mismatches: | ||
|
|
||
| - **Different origin**: Strong fraud warning - likely impersonation attack | ||
| - **Different IP/User-Agent**: Network change warning - could be legitimate or suspicious | ||
| - **Significant time gaps**: Message is not relevant anymore | ||
| - **Missing metadata**: Should not occure after rollout. Messages without metadata should be rejected | ||
|
|
||
| ### User Interface Guidelines | ||
|
|
||
| 1) **Verification Status Messages** | ||
|
|
||
| Wallets should be able to display following statuses: | ||
| - **Verification Mark (ok + whitelisted)**: | ||
| "✅ Verified dApp — confirmed request from a trusted source" | ||
|
|
||
| - **Ok**: | ||
| "No message" | ||
|
|
||
| - **Danger Warning**: | ||
| "⚠️ This request could not be verified and may be fraudulent. Do not proceed unless you are certain of the source." | ||
|
|
||
| - **Warning Message**: | ||
| "⚠️ This request's details differ from your current connection. This could be due to a network change or other unusual event. Proceed with caution." | ||
|
|
||
| 2) **Transaction Source Display** | ||
|
|
||
| In transaction confirmation dialogs, wallets SHOULD display: | ||
|
|
||
| - Request source information (origin, timestamp) | ||
| - Any detected mismatches with stored connection data | ||
| - Clear warnings for security concerns | ||
| - Country of the request origin(from ip) | ||
| - Information about request user agent in the human readable format(e.g. Chrome 113 from macOS) | ||
|
|
||
| 3) **User Education** | ||
|
|
||
| Wallets SHOULD educate users about: | ||
|
|
||
| - Meaning of verification marks and warnings | ||
| - How to identify legitimate vs suspicious connection patterns | ||
| - Best practices for safe dApp interaction | ||
| - When to decline suspicious requests | ||
|
|
||
| ### Security Best Practices | ||
|
|
||
| 1) **Metadata Storage** | ||
|
|
||
| - Store connection metadata securely and encrypted | ||
| - Implement proper session management and cleanup | ||
| - Limit metadata retention to necessary duration | ||
|
|
||
| 2) **Verification Logic** | ||
|
|
||
| - Implement proper cryptographic verification of encrypted metadata | ||
| - Handle edge cases and error conditions gracefully | ||
|
|
||
| 3) **User Safety** | ||
|
|
||
| - Default to more restrictive behavior when verification fails | ||
| - Provide clear actionable guidance to users | ||
| - Never suppress security warnings to improve user experience | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,8 +6,9 @@ | |
| 1. App initiates SSE connection with bridge; | ||
| 2. App passes connection info to the wallet via universal link or deeplink or QR code; | ||
| 3. Wallet connects to the bridge with given parameters, and save connection info locally; | ||
| 4. Wallet sends account information to the app using bridge; | ||
| 5. App receives message and save connection info locally; | ||
| 4. Wallet verifies connection source via `/verify` endpoint; | ||
| 5. Wallet sends account information to the app using bridge; | ||
| 6. App receives message and save connection info locally; | ||
|
|
||
| ### Reconnection with http bridge | ||
| 1. App reads connection info from localstorage | ||
|
|
@@ -22,9 +23,10 @@ | |
| ### Making ordinary requests and responses | ||
| 1. App and wallet are in a connected state | ||
| 2. App generates request and sends it to the bridge | ||
| 3. Bridge forwards message to the wallet | ||
| 4. Wallet generates response and sends it to the bridge | ||
| 5. Bridge forwards message to the app | ||
| 3. Bridge forwards message to the wallet with encrypted request source metadata | ||
| 4. Wallet decrypts and verifies request source metadata | ||
| 5. Wallet generates response and sends it to the bridge | ||
| 6. Bridge forwards message to the app | ||
|
|
||
|
|
||
| ## Details | ||
|
|
@@ -67,7 +69,32 @@ App is not yet in the connected state, and may restart the whole process at any | |
|
|
||
| ### Wallet establishes connection | ||
|
|
||
| Wallet opens up a link or QR code, reads plaintext app’s **Client ID** (A from parameter “**id”**) and [InitialRequest](requests-responses.md#initiating-connection) (from parameter **“r”**). | ||
| Wallet opens up a link or QR code, reads plaintext app's **Client ID** (A from parameter "**id"**) and [InitialRequest](requests-responses.md#initiating-connection) (from parameter **"r"**). | ||
|
|
||
| ### Connection Verification Process | ||
|
|
||
| **For HTTP Bridge connections:** | ||
|
|
||
| 1. **Extract connection details**: Wallet extracts origin, client ID from the connection request | ||
| 2. **Call verification endpoint**: Wallet sends POST request to `${bridgeUrl}/verify`: | ||
| ```json | ||
| { | ||
| "type": "connect", | ||
| "client_id": "<client_id>", | ||
| "origin": "<protocol+domain>" | ||
| } | ||
| ``` | ||
| 3. **Process verification response**: | ||
| - `ok` + whitelisted domain → show verification mark ✅ | ||
| - `danger` → display strong warning, recommend declining | ||
| - `warning` → display caution message | ||
| - `unknown` → proceed without special indicators | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if /verify endpoint is not available or wallet gets an error?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should be treated as |
||
|
|
||
| **User Interface Guidelines:** | ||
| - **Verification Mark (ok + whitelisted)**: "✅ Verified dApp — confirmed request from a trusted source" | ||
| - **ok**: No message for default case | ||
| - **Danger Warning**: "⚠️ This request could not be verified and may be fraudulent. Do not proceed unless you are certain of the source." | ||
| - **Warning Message**: "⚠️ This request's details differ from expected. This could be due to a network change or other unusual event. Proceed with caution." | ||
|
|
||
| Wallet computes the [InitialResponse](requests-responses.md#initiating-connection). | ||
|
|
||
|
|
@@ -93,16 +120,37 @@ When the user performs an action in the app, it may request confirmation from th | |
|
|
||
| App generates a [request](requests-responses.md#messages). | ||
|
|
||
| App encrypts it to the wallet’s key B (see below). | ||
| App encrypts it to the wallet's key B (see below). | ||
|
|
||
| App sends the encrypted message to B over the [Bridge](bridge.md). | ||
|
|
||
| App shows “pending confirmation” UI to let user know to open the wallet. | ||
| **Bridge processes message with verification**: | ||
| 1. Bridge collects request source metadata (origin, IP, User-Agent, timestamp, client ID) | ||
| 2. Bridge encrypts metadata using wallet's Curve25519 public key | ||
| 3. Bridge includes encrypted `request_source` in the BridgeMessage | ||
|
|
||
| App shows "pending confirmation" UI to let user know to open the wallet. | ||
|
|
||
| Wallet receives the encrypted message through the Bridge. | ||
|
|
||
| Wallet decrypts the message and is now assured that it came from the app with ID **A.** | ||
|
|
||
| Wallet shows the confirmation dialog to the user, signs transaction and [replies](requests-responses.md#messages) over the bridge with user’s decision: “Ok, sent” or “User cancelled”. | ||
| ### Transaction Verification Process | ||
|
|
||
| **Request Source Verification:** | ||
| 1. **Decrypt metadata**: Wallet decrypts the `request_source` field from BridgeMessage using its private key | ||
| 2. **Parse metadata**: Extract BridgeRequestSource with origin, IP, User-Agent, timestamp, client ID | ||
| 3. **Compare with stored connection**: Verify metadata matches stored connection details | ||
| 4. **Display warnings for mismatches**: | ||
| - Different origin → potential fraud warning | ||
| - Different IP/User-Agent → network change warning | ||
| - Significant time gaps → reject transaction | ||
|
|
||
| **User Interface for Transaction Verification:** | ||
| - Show request source details in transaction confirmation | ||
| - Highlight any mismatches between connection and transaction metadata | ||
| - Provide clear warnings for potential security issues | ||
|
|
||
| Wallet shows the confirmation dialog to the user, signs transaction and [replies](requests-responses.md#messages) over the bridge with user's decision: "Ok, sent" or "User cancelled". | ||
|
|
||
| App receives the encrypted message, decrypts it and closes the “pending confirmation” UI. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It’s not obvious to a future reader whether we’re in Phase 1 or Phase 2 right now. Could we add something to make the current phase clear? Add dates?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can only add dates after we start the rollout.