Skip to content

Commit ab55bc6

Browse files
Implemented allowed intent class and package names for android push security (#94)
* Implemented allowed intent class and package names for android push notification security * Update CountlyReactNative.java Co-authored-by: ArtursKadikis <kadikis.arturs@gmail.com>
1 parent 965f3a3 commit ab55bc6

File tree

3 files changed

+87
-2
lines changed

3 files changed

+87
-2
lines changed

Countly.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const Countly = {};
1818
Countly.serverUrl = "";
1919
Countly.appKey = "";
2020
_isInitialized = false;
21+
_isPushInitialized = false;
2122
/*
2223
* Listener for rating widget callback, when callback recieve we will remove the callback using listener.
2324
*/
@@ -200,6 +201,7 @@ Countly.askForNotificationPermission = function(customSoundPath = "null"){
200201
return message;
201202
}
202203
CountlyReactNative.askForNotificationPermission([customSoundPath]);
204+
_isPushInitialized = true;
203205
}
204206

205207
/**
@@ -212,6 +214,54 @@ Countly.registerForNotification = function(theListener){
212214
CountlyReactNative.registerForNotification([]);
213215
return event;
214216
};
217+
218+
/**
219+
*
220+
* Configure intent redirection checks for push notification
221+
* Should be called before Countly "askForNotificationPermission"
222+
*
223+
* @param {array of allowed class names } allowedIntentClassNames set allowed intent class names
224+
* @param {array of allowed package names } allowedIntentClassNames set allowed intent package names
225+
* @param {bool to check additional intent checks} useAdditionalIntentRedirectionChecks by default its true
226+
*/
227+
Countly.configureIntentRedirectionCheck = function(allowedIntentClassNames = [], allowedIntentPackageNames = [], useAdditionalIntentRedirectionChecks = true){
228+
if (Platform.OS.match("ios")) return "configureIntentRedirectionCheck : not required for iOS";
229+
230+
if(_isPushInitialized) {
231+
var message = "'configureIntentRedirectionCheck' must be called before 'askForNotificationPermission'";
232+
Countly.logError("configureIntentRedirectionCheck", message);
233+
return message;
234+
}
235+
if(!Array.isArray(allowedIntentClassNames)) {
236+
var message = "Ignoring, unsupported data type '" + (typeof allowedIntentClassNames) + "' 'allowedIntentClassNames' should be an array of String";
237+
Countly.logWarning("configureIntentRedirectionCheck", message);
238+
allowedIntentClassNames = []
239+
}
240+
if(!Array.isArray(allowedIntentPackageNames)) {
241+
var message = "Ignoring, unsupported data type '" + (typeof allowedIntentPackageNames) + "' 'allowedIntentPackageNames' should be an array of String";
242+
Countly.logWarning("configureIntentRedirectionCheck", message);
243+
allowedIntentPackageNames = []
244+
}
245+
246+
if(typeof useAdditionalIntentRedirectionChecks != "boolean") {
247+
var message = "Ignoring, unsupported data type '" + (typeof useAdditionalIntentRedirectionChecks) + "' 'useAdditionalIntentRedirectionChecks' should be a boolean";
248+
Countly.logWarning("configureIntentRedirectionCheck", message);
249+
useAdditionalIntentRedirectionChecks = true
250+
}
251+
252+
var _allowedIntentClassNames = [];
253+
for(var className of allowedIntentClassNames){
254+
_allowedIntentClassNames.push(className.toString());
255+
}
256+
257+
var _allowedIntentPackageNames = [];
258+
for(var packageName of allowedIntentPackageNames){
259+
_allowedIntentPackageNames.push(packageName.toString());
260+
}
261+
262+
CountlyReactNative.configureIntentRedirectionCheck(_allowedIntentClassNames, _allowedIntentPackageNames, useAdditionalIntentRedirectionChecks);
263+
}
264+
215265
// countly start for android
216266
Countly.start = function(){
217267
if(!_isInitialized) {

android/src/main/java/ly/count/android/sdk/react/CountlyReactNative.java

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.io.IOException;
2929
import java.io.InputStreamReader;
3030
import java.util.ArrayList;
31+
import java.util.Collection;
3132
import java.util.Collections;
3233
import java.util.List;
3334
import java.util.Set;
@@ -44,6 +45,7 @@
4445
import androidx.annotation.NonNull;
4546

4647
import ly.count.android.sdk.StarRatingCallback;
48+
import ly.count.android.sdk.messaging.CountlyConfigPush;
4749
import ly.count.android.sdk.messaging.CountlyPush;
4850

4951

@@ -93,6 +95,11 @@ public class CountlyReactNative extends ReactContextBaseJavaModule implements Li
9395
private boolean isOnResumeBeforeInit = false;
9496
private Boolean isSessionStarted_ = false;
9597

98+
99+
private List<String> allowedIntentClassNames = new ArrayList<>();
100+
private List<String> allowedIntentPackageNames = new ArrayList<>();
101+
private boolean useAdditionalIntentRedirectionChecks = true;
102+
96103
private final ReactApplicationContext _reactContext;
97104

98105
private final Set<String> validConsentFeatureNames = new HashSet<>(Arrays.asList(
@@ -587,8 +594,15 @@ public void askForNotificationPermission(ReadableArray args){
587594
notificationManager.createNotificationChannel(channel);
588595
}
589596
}
590-
CountlyPush.useAdditionalIntentRedirectionChecks = true;
591-
CountlyPush.init(activity.getApplication(), messagingMode);
597+
CountlyPush.useAdditionalIntentRedirectionChecks = useAdditionalIntentRedirectionChecks;
598+
CountlyConfigPush configPush = new CountlyConfigPush(activity.getApplication(), messagingMode);
599+
if(allowedIntentClassNames.size() > 0) {
600+
configPush.setAllowedIntentClassNames(allowedIntentClassNames);
601+
}
602+
if(allowedIntentPackageNames.size() > 0) {
603+
configPush.setAllowedIntentPackageNames(allowedIntentPackageNames);
604+
}
605+
CountlyPush.init(configPush);
592606
try{
593607
FirebaseApp.initializeApp(context);
594608
FirebaseMessaging firebaseMessagingInstance = FirebaseMessaging.getInstance();
@@ -620,6 +634,24 @@ public void onComplete(@NonNull Task<String> task) {
620634
}
621635
}
622636

637+
@ReactMethod
638+
public void configureIntentRedirectionCheck(ReadableArray intentClassNames, ReadableArray intentPackageNames, boolean useAdditionalIntentRedirectionChecks){
639+
Countly.sharedInstance();
640+
this.useAdditionalIntentRedirectionChecks = useAdditionalIntentRedirectionChecks;
641+
allowedIntentClassNames.clear();
642+
allowedIntentPackageNames.clear();
643+
644+
for (int i = 0; i < intentClassNames.size(); i++) {
645+
String className = intentClassNames.getString(i);
646+
allowedIntentClassNames.add(className);
647+
}
648+
649+
for (int i = 0; i < intentPackageNames.size(); i++) {
650+
String packageName = intentPackageNames.getString(i);
651+
allowedIntentPackageNames.add(packageName);
652+
}
653+
}
654+
623655
@ReactMethod
624656
public void start(){
625657
if (isSessionStarted_) {

example/Example.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ class Example extends Component {
6565
else {
6666
Countly.enableAttribution(); // Enable to measure your marketing campaign performance by attributing installs from specific campaigns.
6767
}
68+
69+
Countly.configureIntentRedirectionCheck(["MainActivity"], ["com.countly.demo"]);
70+
6871
Countly.setStarRatingDialogTexts("Title", "Message", "Dismiss");
6972
await Countly.init("https://try.count.ly", "YOUR_APP_KEY"); // Initialize the countly SDK.
7073
Countly.appLoadingFinished();

0 commit comments

Comments
 (0)