Use random IDs to match FCM notifications to accounts

This commit is contained in:
Grishka 2022-05-03 03:01:18 +03:00
parent fa75570254
commit d4e4d9fcde
4 changed files with 25 additions and 6 deletions

View File

@ -9,7 +9,7 @@ android {
applicationId "org.joinmastodon.android" applicationId "org.joinmastodon.android"
minSdk 23 minSdk 23
targetSdk 31 targetSdk 31
versionCode 34 versionCode 35
versionName "1.0.4" versionName "1.0.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@ -18,6 +18,7 @@ import android.util.Log;
import org.joinmastodon.android.api.MastodonAPIController; import org.joinmastodon.android.api.MastodonAPIController;
import org.joinmastodon.android.api.requests.notifications.GetNotificationByID; import org.joinmastodon.android.api.requests.notifications.GetNotificationByID;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Account; import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.PushNotification; import org.joinmastodon.android.model.PushNotification;
@ -52,10 +53,23 @@ public class PushNotificationReceiver extends BroadcastReceiver{
String k=intent.getStringExtra("k"); String k=intent.getStringExtra("k");
String p=intent.getStringExtra("p"); String p=intent.getStringExtra("p");
String s=intent.getStringExtra("s"); String s=intent.getStringExtra("s");
String accountID=intent.getStringExtra("x"); String pushAccountID=intent.getStringExtra("x");
if(!TextUtils.isEmpty(accountID) && !TextUtils.isEmpty(k) && !TextUtils.isEmpty(p) && !TextUtils.isEmpty(s)){ if(!TextUtils.isEmpty(pushAccountID) && !TextUtils.isEmpty(k) && !TextUtils.isEmpty(p) && !TextUtils.isEmpty(s)){
MastodonAPIController.runInBackground(()->{ MastodonAPIController.runInBackground(()->{
try{ try{
List<AccountSession> accounts=AccountSessionManager.getInstance().getLoggedInAccounts();
AccountSession account=null;
for(AccountSession acc:accounts){
if(pushAccountID.equals(acc.pushAccountID)){
account=acc;
break;
}
}
if(account==null){
Log.w(TAG, "onReceive: account for id '"+pushAccountID+"' not found");
return;
}
String accountID=account.getID();
PushNotification pn=AccountSessionManager.getInstance().getAccount(accountID).getPushSubscriptionManager().decryptNotification(k, p, s); PushNotification pn=AccountSessionManager.getInstance().getAccount(accountID).getPushSubscriptionManager().decryptNotification(k, p, s);
new GetNotificationByID(pn.notificationId+"") new GetNotificationByID(pn.notificationId+"")
.setCallback(new Callback<>(){ .setCallback(new Callback<>(){

View File

@ -126,7 +126,7 @@ public class PushSubscriptionManager{
throw new IllegalStateException("No device push token available"); throw new IllegalStateException("No device push token available");
MastodonAPIController.runInBackground(()->{ MastodonAPIController.runInBackground(()->{
Log.d(TAG, "registerAccountForPush: started for "+accountID); Log.d(TAG, "registerAccountForPush: started for "+accountID);
String encodedPublicKey, encodedAuthKey; String encodedPublicKey, encodedAuthKey, pushAccountID;
try{ try{
KeyPairGenerator generator=KeyPairGenerator.getInstance("EC"); KeyPairGenerator generator=KeyPairGenerator.getInstance("EC");
ECGenParameterSpec spec=new ECGenParameterSpec(EC_CURVE_NAME); ECGenParameterSpec spec=new ECGenParameterSpec(EC_CURVE_NAME);
@ -136,13 +136,17 @@ public class PushSubscriptionManager{
privateKey=keyPair.getPrivate(); privateKey=keyPair.getPrivate();
encodedPublicKey=Base64.encodeToString(serializeRawPublicKey(publicKey), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING); encodedPublicKey=Base64.encodeToString(serializeRawPublicKey(publicKey), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
authKey=new byte[16]; authKey=new byte[16];
new SecureRandom().nextBytes(authKey); SecureRandom secureRandom=new SecureRandom();
secureRandom.nextBytes(authKey);
byte[] randomAccountID=new byte[16];
secureRandom.nextBytes(randomAccountID);
AccountSession session=AccountSessionManager.getInstance().tryGetAccount(accountID); AccountSession session=AccountSessionManager.getInstance().tryGetAccount(accountID);
if(session==null) if(session==null)
return; return;
session.pushPrivateKey=Base64.encodeToString(privateKey.getEncoded(), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING); session.pushPrivateKey=Base64.encodeToString(privateKey.getEncoded(), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
session.pushPublicKey=Base64.encodeToString(publicKey.getEncoded(), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING); session.pushPublicKey=Base64.encodeToString(publicKey.getEncoded(), Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
session.pushAuthKey=encodedAuthKey=Base64.encodeToString(authKey, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING); session.pushAuthKey=encodedAuthKey=Base64.encodeToString(authKey, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
session.pushAccountID=pushAccountID=Base64.encodeToString(randomAccountID, Base64.URL_SAFE | Base64.NO_WRAP | Base64.NO_PADDING);
AccountSessionManager.getInstance().writeAccountsFile(); AccountSessionManager.getInstance().writeAccountsFile();
}catch(NoSuchAlgorithmException|InvalidAlgorithmParameterException e){ }catch(NoSuchAlgorithmException|InvalidAlgorithmParameterException e){
Log.e(TAG, "registerAccountForPush: error generating encryption key", e); Log.e(TAG, "registerAccountForPush: error generating encryption key", e);
@ -153,7 +157,7 @@ public class PushSubscriptionManager{
encodedAuthKey, encodedAuthKey,
subscription==null ? PushSubscription.Alerts.ofAll() : subscription.alerts, subscription==null ? PushSubscription.Alerts.ofAll() : subscription.alerts,
subscription==null ? PushSubscription.Policy.ALL : subscription.policy, subscription==null ? PushSubscription.Policy.ALL : subscription.policy,
accountID) pushAccountID)
.setCallback(new Callback<>(){ .setCallback(new Callback<>(){
@Override @Override
public void onSuccess(PushSubscription result){ public void onSuccess(PushSubscription result){

View File

@ -27,6 +27,7 @@ public class AccountSession{
public boolean needUpdatePushSettings; public boolean needUpdatePushSettings;
public long filtersLastUpdated; public long filtersLastUpdated;
public List<Filter> wordFilters=new ArrayList<>(); public List<Filter> wordFilters=new ArrayList<>();
public String pushAccountID;
private transient MastodonAPIController apiController; private transient MastodonAPIController apiController;
private transient StatusInteractionController statusInteractionController; private transient StatusInteractionController statusInteractionController;
private transient CacheController cacheController; private transient CacheController cacheController;