diff --git a/native/android/app/src/main/java/app/comm/android/commservices/CommAndroidDeleteBlobWork.java b/native/android/app/src/main/java/app/comm/android/commservices/CommAndroidDeleteBlobWork.java --- a/native/android/app/src/main/java/app/comm/android/commservices/CommAndroidDeleteBlobWork.java +++ b/native/android/app/src/main/java/app/comm/android/commservices/CommAndroidDeleteBlobWork.java @@ -26,15 +26,15 @@ @Override public Result doWork() { String blobHash = - getInputData().getString(CommAndroidBlobClient.BLOB_HASH_KEY); + getInputData().getString(CommAndroidServicesClient.BLOB_HASH_KEY); String blobHolder = - getInputData().getString(CommAndroidBlobClient.BLOB_HOLDER_KEY); + getInputData().getString(CommAndroidServicesClient.BLOB_HOLDER_KEY); String jsonBody; try { jsonBody = new JSONObject() - .put(CommAndroidBlobClient.BLOB_HASH_KEY, blobHash) - .put(CommAndroidBlobClient.BLOB_HOLDER_KEY, blobHolder) + .put(CommAndroidServicesClient.BLOB_HASH_KEY, blobHash) + .put(CommAndroidServicesClient.BLOB_HOLDER_KEY, blobHolder) .toString(); } catch (JSONException e) { // This should never happen since the code @@ -50,7 +50,7 @@ String authToken; try { - authToken = CommAndroidBlobClient.getAuthToken(); + authToken = CommAndroidServicesClient.getAuthToken(); } catch (JSONException e) { // In this case however it may happen that // auth metadata got corrupted but will be @@ -61,15 +61,16 @@ RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), jsonBody); - Request request = new Request.Builder() - .delete(requestBody) - .url(CommAndroidBlobClient.BLOB_SERVICE_URL + "/blob") - .header("Authorization", authToken) - .build(); + Request request = + new Request.Builder() + .delete(requestBody) + .url(CommAndroidServicesClient.BLOB_SERVICE_URL + "/blob") + .header("Authorization", authToken) + .build(); try { Response response = - CommAndroidBlobClient.httpClient.newCall(request).execute(); + CommAndroidServicesClient.httpClient.newCall(request).execute(); if (response.isSuccessful()) { return Result.success(); } diff --git a/native/android/app/src/main/java/app/comm/android/commservices/CommAndroidBlobClient.java b/native/android/app/src/main/java/app/comm/android/commservices/CommAndroidServicesClient.java rename from native/android/app/src/main/java/app/comm/android/commservices/CommAndroidBlobClient.java rename to native/android/app/src/main/java/app/comm/android/commservices/CommAndroidServicesClient.java --- a/native/android/app/src/main/java/app/comm/android/commservices/CommAndroidBlobClient.java +++ b/native/android/app/src/main/java/app/comm/android/commservices/CommAndroidServicesClient.java @@ -21,7 +21,7 @@ import org.json.JSONException; import org.json.JSONObject; -public class CommAndroidBlobClient { +public class CommAndroidServicesClient { // The FirebaseMessagingService docs state that message // processing should complete within at most 20 seconds // window. Therefore we limit http time call to 15 seconds @@ -37,6 +37,9 @@ public static final String BLOB_SERVICE_URL = BuildConfig.DEBUG ? "https://blob.staging.commtechnologies.org" : "https://blob.commtechnologies.org"; + public static final String IDENTITY_SERVICE_URL = BuildConfig.DEBUG + ? "https://identity.staging.commtechnologies.org:51004" + : "https://identity.commtechnologies.org:51004"; public static final String BLOB_HASH_KEY = "blob_hash"; public static final String BLOB_HOLDER_KEY = "holder"; @@ -57,6 +60,62 @@ return response.body().bytes(); } + public JSONObject getNotifsInboundKeysForDeviceSync(String deviceID) + throws IOException, JSONException { + String authToken = getAuthToken(); + String base64URLEncodedDeviceID = + deviceID.replaceAll("\\+", "-").replaceAll("\\/", "_"); + + Request request = + new Request.Builder() + .get() + .url( + IDENTITY_SERVICE_URL + + "/device_inbound_keys?device_id=" + base64URLEncodedDeviceID) + .header("Authorization", authToken) + .build(); + Response response = httpClient.newCall(request).execute(); + if (!response.isSuccessful()) { + throw new RuntimeException( + "Failed to fetch inbound keys for device: " + deviceID + + " from identity service. Response error code: " + response); + } + + String serializedResponse = response.body().string(); + JSONObject responseObject = new JSONObject(serializedResponse); + + JSONObject identityKeyInfo = + responseObject.optJSONObject("identityKeyInfo"); + if (identityKeyInfo == null) { + throw new RuntimeException( + "identityKeyInfo missing in identity service response"); + } + + String keyPayload = identityKeyInfo.optString("keyPayload"); + if (keyPayload == null) { + throw new RuntimeException( + "keyPayload missing in identity service response"); + } + + JSONObject identityKeys = new JSONObject(keyPayload); + JSONObject notificationIdentityKeys = + identityKeys.optJSONObject("notificationIdentityPublicKeys"); + if (notificationIdentityKeys == null) { + throw new RuntimeException( + "notificationIdentityKeys missing in identity service response"); + } + + String curve25519 = notificationIdentityKeys.optString("curve25519"); + String ed25519 = notificationIdentityKeys.optString("ed25519"); + + if (curve25519 == null || ed25519 == null) { + throw new RuntimeException( + "ed25519 or curve25519 missing in identity service response"); + } + + return notificationIdentityKeys; + } + public void scheduleDeferredBlobDeletion( String blobHash, String blobHolder, diff --git a/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java b/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java --- a/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java +++ b/native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java @@ -19,7 +19,7 @@ import app.comm.android.MainActivity; import app.comm.android.R; import app.comm.android.aescrypto.AESCryptoModuleCompat; -import app.comm.android.commservices.CommAndroidBlobClient; +import app.comm.android.commservices.CommAndroidServicesClient; import app.comm.android.fbjni.CommMMKV; import app.comm.android.fbjni.CommSecureStore; import app.comm.android.fbjni.GlobalDBSingleton; @@ -69,7 +69,7 @@ private Bitmap displayableNotificationLargeIcon; private NotificationManager notificationManager; private LocalBroadcastManager localBroadcastManager; - private CommAndroidBlobClient blobClient; + private CommAndroidServicesClient servicesClient; private AESCryptoModuleCompat aesCryptoModule; public static final String RESCIND_KEY = "rescind"; @@ -93,7 +93,7 @@ localBroadcastManager = LocalBroadcastManager.getInstance(this); displayableNotificationLargeIcon = BitmapFactory.decodeResource( this.getApplicationContext().getResources(), R.mipmap.ic_launcher); - blobClient = new CommAndroidBlobClient(); + servicesClient = new CommAndroidServicesClient(); aesCryptoModule = new AESCryptoModuleCompat(); } @@ -330,13 +330,13 @@ String blobHash = message.getData().get(BLOB_HASH_KEY); String blobHolder = message.getData().get(BLOB_HOLDER_KEY); try { - byte[] largePayload = blobClient.getBlobSync(blobHash); + byte[] largePayload = servicesClient.getBlobSync(blobHash); message = aesDecryptRemoteMessage(message, largePayload); handleMessageInfosPersistence(message); } catch (Exception e) { Log.w("COMM", "Failure when handling large notification.", e); } - blobClient.scheduleDeferredBlobDeletion( + servicesClient.scheduleDeferredBlobDeletion( blobHash, blobHolder, this.getApplicationContext()); }