This ADR proposes adding a new opt-in alternative to the current verification code mechanism
in Decentraland's sign-in flow: a more secure deep link token verification approach. The
current system requires users to manually verify a code displayed in the client matches the
one shown during web-based social login, which contributes to a high entry flow drop rate and
is vulnerable to session hijacking attacks when authentication URLs are shared. The proposed
deep link approach uses OS-level protocol handling to ensure tokens are delivered only to the
local client, preventing impersonation attacks while significantly improving user experience
by eliminating the manual verification step. This streamlined flow aims to reduce user
abandonment during onboarding. The existing verification code mechanism will remain as the
default authentication method, with the deep link flow available via an explicit
use_token=true parameter.
The existing Decentraland sign-in process works as follows:
sequenceDiagram
participant User as 👤 User
participant Client as 💻 Decentraland Client
participant Browser as 🌐 Browser
participant Server as 🔒 Auth Server
User->>Client: Presses "Sign In" button
Client->>Client: Generates session & displays verification code (e.g., "67")
Client->>Browser: Opens auth URL with session token
User->>Browser: Completes social login (Google, etc.)
Browser->>User: Shows "Verify code: is it 67? YES/NO"
User->>User: Manually checks code displayed in Client
User->>Browser: Clicks YES
Browser->>Server: Confirms verification
Server->>Client: Sends AUTH CHAIN
Client->>Client: User authenticated
The current verification code flow has significant user experience friction:
This friction contributes to a high entry flow drop rate, where users abandon the sign-in process before completion, negatively impacting user acquisition and retention. Reducing this friction is critical for improving the onboarding experience and reducing user abandonment.
The current implementation is vulnerable to URL-based session fixation/hijacking attacks. A malicious user can execute this attack:
This vulnerability exists because:
sequenceDiagram
participant AttackerUser as 🔴 Malicious User
participant AttackerClient as 🔴 Malicious User's Client
participant LegitUser as ✅ Legitimate User
participant LegitBrowser as ✅ Legitimate User's Browser
participant Server as 🔒 Auth Server
rect rgb(255, 230, 230)
Note over AttackerUser,AttackerClient: 🔴 MALICIOUS: Attacker initiates sign-in
AttackerUser->>AttackerClient: Presses "Sign In"
AttackerClient->>AttackerClient: Generates session & displays verification code "67"
AttackerClient->>AttackerClient: Creates auth URL
end
Note over AttackerUser,LegitUser: ⚠️ ATTACK VECTOR: Social engineering
AttackerUser->>LegitUser: Sends auth URL (e.g., via email, chat, phishing)
rect rgb(230, 255, 230)
Note over LegitUser,LegitBrowser: ✅ VICTIM: Unsuspecting legitimate user
LegitUser->>LegitBrowser: Opens auth URL (thinks it's safe)
LegitUser->>LegitBrowser: Completes their social login (Google, etc.)
LegitBrowser->>LegitUser: Shows "Verify code: is it 67? YES/NO"
Note over LegitUser: Victim assumes this is legitimate
LegitUser->>LegitBrowser: Clicks YES
LegitBrowser->>Server: Confirms verification with legitimate user's identity
end
rect rgb(255, 200, 200)
Note over Server,AttackerClient: ⚠️ VULNERABILITY: AUTH CHAIN sent to wrong client!
Server->>AttackerClient: Sends AUTH CHAIN (with legitimate user's identity)
Note over AttackerClient: 🔴 ATTACK SUCCESS!<br/>Attacker's client authenticated with victim's identity
AttackerClient->>AttackerClient: Can now impersonate legitimate user
end
This decision addresses two critical issues:
1. User Experience and Onboarding
The current entry flow has a high drop rate, meaning many users abandon the sign-in process before completion. This negatively impacts:
Improving the sign-in flow is essential for reducing abandonment and growing the Decentraland community.
2. Security
The AUTH CHAIN grants critical capabilities within Decentraland, including the ability to sign transactions and perform actions on behalf of a user's identity. A successful impersonation attack could allow malicious actors to:
Description: Continue to use the current verification code system as the default authentication method.
Benefits:
Drawbacks:
Status: This option WILL remain as the default authentication method. The new deep link
approach will be available as an opt-in alternative via the
use_token=true parameter.
Description: Implement a new authentication flow using OS-level deep link protocol handling as an alternative to the verification code.
Flow:
use_token=true parameter)
decentraland://?token=<secure_token>sequenceDiagram
participant User as 👤 User
participant Client as 💻 Decentraland Client
participant Browser as 🌐 Browser
participant OS as ⚙️ Operating System
participant Server as 🔒 Auth Server
User->>Client: Presses "Sign In" button
Client->>Browser: Opens auth URL (use_token=true)
User->>Browser: Completes social login (Google, etc.)
Browser->>Server: Authentication successful
Server->>Server: Generates secure token
Server->>Browser: Return success with token
Browser->>OS: Opens deep link decentraland://?token=abc123...
OS->>Client: Routes deep link to Client
Client->>Client: Extracts token from deep link
Client->>Server: Sends token for validation
Server->>Server: Validates token (single-use, not expired)
Server->>Client: Sends AUTH CHAIN
Client->>Client: User authenticated
Benefits:
The following diagram demonstrates why the deep link approach prevents the impersonation attack:
sequenceDiagram
participant AttackerUser as 🔴 Malicious User
participant AttackerClient as 🔴 Malicious User's Client
participant LegitUser as ✅ Legitimate User
participant LegitBrowser as ✅ Legitimate User's Browser
participant LegitOS as ✅ Legitimate User's OS
participant Server as 🔒 Auth Server
rect rgb(255, 230, 230)
Note over AttackerUser,AttackerClient: 🔴 MALICIOUS: Attacker initiates sign-in
AttackerUser->>AttackerClient: Presses "Sign In"
AttackerClient->>AttackerClient: Generates session
AttackerClient->>AttackerClient: Creates auth URL (use_token=true)
end
Note over AttackerUser,LegitUser: ⚠️ ATTACK VECTOR: Social engineering
AttackerUser->>LegitUser: Sends auth URL (social engineering)
rect rgb(230, 255, 230)
Note over LegitUser,Server: ✅ VICTIM: Opens URL on THEIR machine
LegitUser->>LegitBrowser: Opens auth URL
LegitUser->>LegitBrowser: Completes their social login
LegitBrowser->>Server: Authentication successful (legitimate user's identity)
Server->>Server: Generates secure token for session
Server->>LegitBrowser: Return success with token
end
rect rgb(200, 255, 200)
Note over LegitBrowser,LegitOS: 🛡️ PROTECTION: Deep link opens on victim's machine
LegitBrowser->>LegitOS: Opens deep link decentraland://?token=abc123...
LegitOS->>LegitOS: OS routes to local Decentraland client
Note over LegitOS: ✅ Token delivered to victim's machine ONLY<br/>Cannot reach attacker's client!
end
rect rgb(255, 200, 200)
Note over AttackerClient: 🔴 ATTACK BLOCKED!
Note over AttackerClient: ✗ Attacker's client never receives the token<br/>✗ Token was delivered via OS on victim's machine<br/>✗ Attacker CANNOT get AUTH CHAIN
end
rect rgb(230, 255, 230)
Note over LegitUser: ✅ Security preserved:<br/>Only victim's machine can receive the token
end
Drawbacks:
Security Analysis: This approach is fundamentally more secure because:
Description: Add server-side validation that the web session and client connection originate from the same IP address as an extra security layer.
Benefits:
Drawbacks:
Status: This is an optional additional security measure that MAY be implemented alongside Option 2 to provide defense-in-depth, but should NOT be relied upon as the primary security mechanism.
Implement Option 2 (Deep Link Token Verification) as an opt-in alternative authentication
method
(via use_token=true parameter), while
keeping Option 1 (Verification Code) as the default authentication method.
Option 3 (IP-Based Verification) MAY be added as an additional security layer for
defense-in-depth.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
The client MUST generate or receive an authentication session URL that the user opens in their web browser.
The web application MUST:
Upon successful social login, the server MUST:
The web application MUST:
decentraland://?token=<secure_token>The Decentraland client MUST:
decentraland:// protocol handler with the operating systemThe server MUST:
The server SHOULD implement rate limiting on token validation attempts to prevent brute force attacks.
The client SHOULD handle the following error cases:
The system SHALL use the verification code flow as the default authentication method. The deep link token verification flow SHALL be opt-in via a query parameter:
https://auth.decentraland.org/login?session=<id>&use_token=true
Default behavior (no parameter or use_token=false):
Opt-in behavior (use_token=true):
As an additional security layer, the server MAY verify that the IP address of the client requesting the AUTH CHAIN matches (or is reasonably close to) the IP address from which the social login was completed.
The server SHOULD:
For web-based explorers or environments where a native client is not available, alternative authentication mechanisms MUST be provided (outside the scope of this ADR).
use_token=true parameter
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.