Securing Deeplinks in Android

Cyberspecs
3 min readJun 5, 2024

--

Hello folks, I’m back with another write-up, and today I have something even more interesting for you guys as I have linked my short on the given topic to save you some time and prepare you for this topic in just 1 minute. Obviously, for more details, you can dig into my article and check the code snippets attached. Hope you enjoy this as much as I enjoyed putting it up. Do check out other shorts on my YouTube and subscribe for more on this!

Introduction

Deep linking in Android allows apps to open specific content directly via a URL. While this feature enhances user experience by providing a seamless transition between web and app content, it also poses potential security risks. If not handled correctly, deep links can be exploited to bypass authentication or inject malicious data. This article explores strategies to secure deep links in your Android app and provides code snippets to help you implement these strategies.

Understanding Deep Links

Deep links can be categorized into three types:

  1. Traditional Deep Links: Links that can open the app if it’s already installed.
  2. App Links: Verified links that open the app if installed or fall back to the web otherwise.
  3. Custom Scheme URLs: Links using a custom URL scheme defined by the app.

Security Risks of Deep Links

  • Unauthenticated Access: Deep links can expose sensitive parts of the app if they aren’t properly authenticated.
  • Parameter Tampering: Attackers can manipulate the parameters in deep links to exploit vulnerabilities.
  • Phishing Attacks: Deep links can be used to redirect users to malicious websites.

Best Practices for Securing Deep Links

1. Validate Incoming Deep Links

Ensure that the deep links being handled are from trusted sources. Use App Links to verify the ownership of URLs.

<!-- AndroidManifest.xml -->
<activity
android:name=".MainActivity">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<!-- Accepts URIs that begin with "https://www.example.com/gizmos” -->
<data android:scheme="https"
android:host="www.example.com"
android:pathPrefix="/gizmos" />
</intent-filter>
</activity>

2. Authenticate Users

Before granting access to sensitive content via deep links, ensure the user is authenticated.

// MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Intent intent = getIntent();
Uri data = intent.getData();

if (data != null) {
// Check if the user is authenticated
if (!isUserAuthenticated()) {
// Redirect to login screen
redirectToLogin();
} else {
// Process the deep link
handleDeepLink(data);
}
}
}

private boolean isUserAuthenticated() {
// Implement your authentication logic here
return true; // Placeholder for demonstration
}

private void redirectToLogin() {
Intent loginIntent = new Intent(this, LoginActivity.class);
startActivity(loginIntent);
}

3. Validate Parameters

Always validate and sanitize parameters extracted from deep links to prevent tampering and injection attacks.

private void handleDeepLink(Uri data) {
String itemId = data.getQueryParameter("item_id");

if (itemId != null && isValidItemId(itemId)) {
// Load the item
loadItem(itemId);
} else {
// Handle invalid item_id
showError();
}
}

private boolean isValidItemId(String itemId) {
// Implement your validation logic here
return itemId.matches("\\d+"); // Example: item_id should be a number
}

private void showError() {
Toast.makeText(this, "Invalid item ID", Toast.LENGTH_SHORT).show();
}

4. Use HTTPS

Always use HTTPS to ensure data transmitted via deep links is encrypted.

<!-- AndroidManifest.xml -->
<activity
android:name=".MainActivity">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<!-- Accepts only secure URIs that begin with "https://www.example.com" -->
<data android:scheme="https"
android:host="www.example.com" />
</intent-filter>
</activity>

5. Implement Deep Link Verification

For App Links, use the Digital Asset Links file to verify your domain.

  1. Host an assetlinks.json file on your website:
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.example.app",
"sha256_cert_fingerprints": ["<YOUR_APP_CERTIFICATE_SHA256_FINGERPRINT>"]
}
}
]

2. Verify the Digital Asset Links file:

<!-- AndroidManifest.xml -->
<activity
android:name=".MainActivity">
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<!-- Accepts only secure URIs that begin with "https://www.example.com" -->
<data android:scheme="https"
android:host="www.example.com" />
</intent-filter>
</activity>

6. Restrict Access to Sensitive Activities

Use permissions and custom schemes judiciously to restrict access to sensitive activities.

<!-- AndroidManifest.xml -->
<activity
android:name=".SensitiveActivity"
android:permission="com.example.app.permission.SENSITIVE_ACTIVITY">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="example"
android:host="sensitive" />
</intent-filter>
</activity>

Securing deep links in your Android app is crucial to prevent unauthorized access and exploitation. By validating deep links, authenticating users, sanitizing parameters, using HTTPS, and implementing deep link verification, you can significantly enhance the security of your app. Follow these best practices and use the provided code snippets to secure your Android app effectively.

--

--