Repository navigation
Conversation
…roid come from the plugin Other apps can start the launch activity with SELECT_NOTIFICATION or SELECT_FOREGROUND_NOTIFICATION intents, and the plugin reported them as notification responses. The plugin now signs the intents of the notifications it shows with an HMAC keyed by a per-install secret and ignores intents without a valid signature. Verification can be turned off with AndroidInitializationSettings.verifyNotificationIntents.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2848.
On Android, any app can start the launch activity with a
SELECT_NOTIFICATIONorSELECT_FOREGROUND_NOTIFICATIONintent, and the plugin reports it as a notification response with the payload, action id and other details taken from the intent. This PR makes the plugin sign the intents of the notifications it shows and ignore intents without a valid signature.Changes
NotificationIntentSigner. It computes an HMAC-SHA256 of the intent's action and the extras the plugin reads: notification id, tag, action id,cancelNotificationand payload. The key is 32 random bytes fromSecureRandom, created on first use and stored ingetNoBackupFilesDir(), so it isn't included in backups.createNotification()signs the intent for tapping the notification and the intents for actions withshowsUserInterface: true. These are the only intents that go to the launch activity. Scheduled and foreground service notifications are built throughcreateNotification()too, so they are signed as well. Actions handled byActionBroadcastReceiveraren't affected, because the receiver isn't exported.getNotificationAppLaunchDetails(),onNewIntent()andonAttachedToActivity()accept an intent only if its signature is valid. Otherwise the launch is treated as a normal one:didNotificationLaunchAppisfalse,onDidReceiveNotificationResponseisn't called, no notification is cancelled, and a warning is logged.AndroidInitializationSettings.verifyNotificationIntents,trueby default. Setting it tofalserestores the old behaviour, for apps that start the launch activity with these intents themselves. The value is saved in the plugin's shared preferences oninitialize(), so it's also available when the plugin handles the launch intent beforeinitialize()is called.The reply text of an action with inputs isn't covered by the signature. The system adds it to the intent when the user replies, and other apps can't attach it to a signed intent because they can't get one.
Compatibility
Notifications shown by an earlier version of the plugin aren't signed. If one of them is still showing after the app is updated, tapping it opens the app without the payload. On the device I tested, installing the update removed the app's notifications, so this didn't come up there.
Because of this and the new default, I think the change fits a major release such as 23.0.0. I haven't added a changelog entry, since you usually write those. I'm happy to add one, or a section in the readme, if you'd like.
Testing
NotificationIntentSignerTest(Robolectric, 11 tests). A signed intent verifies. An unsigned intent, an intent with a forged signature, and a signed intent with any signed field changed or removed don't.initializeand added one forverifyNotificationIntents: false.melos run analyze,flutter testinflutter_local_notifications, and./gradlew flutter_local_notifications:testDebugfrom the example app pass.SELECT_FOREGROUND_NOTIFICATIONintent delivers the forged action id, and withcancelNotificationit cancels the notification with the given id.showsUserInterface: true) deliversid_3and the payload.verifyNotificationIntents: false, the forged intents are accepted again, both when the app is running and on a cold start.