[firebase_messaging]: getToken() does not work on Safari, works on Chrome and Firefox. 'Request contains an invalid argument'
Is there an existing issue for this?
- [X] I have searched the existing issues.
Which plugins are affected?
Messaging
Which platforms are affected?
Web
Description
Firebase Cloud Messaging does not work on Safari, getToken() raises an exception. Works fine with Chrome and Firefox.
Reproducing the issue
You need a valid Firebase account and a vapidKey to replicate this issue with the instructions below.
Please carefully follow the steps described here to replicate the issue.
----Code preparation----
- Create a new Flutter application with
flutter create firetestapp --platforms web. In thewebfolder, add an emptyfirebase-messaging-sw.jsfile (I usually add a comment in this file to be on the safe side). - In the
pubspec.yamlfile, add the following dependencies
firebase_core: ^3.1.1
firebase_messaging: ^15.0.2
The same issue can be seen with firebase_core: ^2.32.0 and firebase_messaging: ^14.9.4.
4. From your prompt do a dart pub global activate flutterfire_cli. For my tests, I used [email protected]
5. firebase login. Log yourself in if necessary.
6. flutterfire configure. Select your Firebase project, just select the 'web' target and let the program do its job.
7. Modify the main.dart file this way:
Add this at the start of the file:
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
and change the _incrementCounter() function to look like this (do a copy/paste):
void _incrementCounter() async {
try {
setState(() {
_text = "Calling initializeApp";
});
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform);
setState(() {
_text = "Calling getToken";
});
// Wait a bit, this works around a bug whereby the service worker may not be ready yet, see:
// https://github.com/firebase/firebase-js-sdk/issues/7575
// https://github.com/firebase/flutterfire/issues/12415
// https://github.com/firebase/flutterfire/issues/11954
await Future.delayed(const Duration(seconds: 2), () {});
const vapidKey =
'PUT_YOUR_VAPID_KEY_HERE';
// The problem happens here
var token = await FirebaseMessaging.instance.getToken(vapidKey: vapidKey);
setState(() {
_text = token ?? "null";
_counter++;
});
} catch (err) {
setState(() {
_text = err.toString();
});
}
}
----Running the code----
- Run the app on Safari. I use macOS Ventura, Safari 17.5.
- Click the '+' button at the bottom right corner of the page
- When the notification permission popup is displayed, click the 'Authorize' button.
- Surprisingly, even though the 'Authorize' button was clicked, an exception is raised:
[firebase_messaging/permission_blocked] Messaging: The notification permission was not granted and blocked instead. - Refresh the page. Click the '+' button again. This time, the notification permission dialog does not show up, suggesting the permission is granted (as it should be). It can be verified that the permission at this point is indeed granted by calling
FirebaseMessaging.instance.requestPermission(), which does returnAuthorizationStatus.granted. - At this point the authorization is granted.
getToken()now raises the following exception:[firebase_messaging/token-subscribe-failed] Messaging: A problem occurred while subscribing the user to FCM. Request contains an invalid argument.
In the Safari Developer Tools, one can see that service workers are running (both flutter's and firebase's (firebase-messaging-sw.js))
Firebase Core version
3.1.1
Flutter Version
3.22.2
Relevant Log Output
See the exception text in the code above.
Flutter dependencies
Expand Flutter dependencies snippet
Dart SDK 3.4.3
Flutter SDK 3.22.2
firetestapp 1.0.0+1
dependencies:
- cupertino_icons 1.0.8
- firebase_auth 5.1.1 [firebase_auth_platform_interface firebase_auth_web firebase_core firebase_core_platform_interface flutter meta]
- firebase_core 3.1.1 [firebase_core_platform_interface firebase_core_web flutter meta]
- firebase_messaging 15.0.2 [firebase_core firebase_core_platform_interface firebase_messaging_platform_interface firebase_messaging_web flutter meta]
- flutter 0.0.0 [characters collection material_color_utilities meta vector_math sky_engine]
dev dependencies:
- flutter_lints 3.0.2 [lints]
- flutter_test 0.0.0 [flutter test_api matcher path fake_async clock stack_trace vector_math leak_tracker_flutter_testing async boolean_selector characters collection leak_tracker leak_tracker_testing material_color_utilities meta source_span stream_channel string_scanner term_glyph vm_service]
transitive dependencies:
- _flutterfire_internals 1.3.38 [collection firebase_core firebase_core_platform_interface flutter meta]
- async 2.11.0 [collection meta]
- boolean_selector 2.1.1 [source_span string_scanner]
- characters 1.3.0
- clock 1.1.1
- collection 1.18.0
- fake_async 1.3.1 [clock collection]
- firebase_auth_platform_interface 7.4.1 [_flutterfire_internals collection firebase_core flutter meta plugin_platform_interface]
- firebase_auth_web 5.12.3 [firebase_auth_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins http_parser meta web]
- firebase_core_platform_interface 5.1.0 [collection flutter flutter_test meta plugin_platform_interface]
- firebase_core_web 2.17.2 [firebase_core_platform_interface flutter flutter_web_plugins meta web]
- firebase_messaging_platform_interface 4.5.40 [_flutterfire_internals firebase_core flutter meta plugin_platform_interface]
- firebase_messaging_web 3.8.10 [_flutterfire_internals firebase_core firebase_core_web firebase_messaging_platform_interface flutter flutter_web_plugins meta web]
- flutter_web_plugins 0.0.0 [flutter characters collection material_color_utilities meta vector_math]
- http_parser 4.0.2 [collection source_span string_scanner typed_data]
- leak_tracker 10.0.4 [clock collection meta path vm_service]
- leak_tracker_flutter_testing 3.0.3 [flutter leak_tracker leak_tracker_testing matcher meta]
- leak_tracker_testing 3.0.1 [leak_tracker matcher meta]
- lints 3.0.0
- matcher 0.12.16+1 [async meta stack_trace term_glyph test_api]
- material_color_utilities 0.8.0 [collection]
- meta 1.12.0
- path 1.9.0
- plugin_platform_interface 2.1.8 [meta]
- sky_engine 0.0.99
- source_span 1.10.0 [collection path term_glyph]
- stack_trace 1.11.1 [path]
- stream_channel 2.1.2 [async]
- string_scanner 1.2.0 [source_span]
- term_glyph 1.2.1
- test_api 0.7.0 [async boolean_selector collection meta source_span stack_trace stream_channel string_scanner term_glyph]
- typed_data 1.3.2 [collection]
- vector_math 2.1.4
- vm_service 14.2.1
- web 0.5.1
Additional context and comments
The piece of code given in this issue works fine with both Google Chrome and Mozilla Firefox. Only Safari has a problem.
@andynewman10 Thank you for reporting this issue. I've tested the example app found here: https://github.com/firebase/flutterfire/tree/master/packages/firebase_messaging/firebase_messaging/example, and I found that after clicking on request permissions and refreshing the page, it works without issues. Can you try and see if the example app works for you, or if you still face the same issue?
Your example does not work on my setup when using Safari.
All tests done on macOS Ventura 13.6.7, Safari 17.5
- On Chrome, when the page appears, the Authorization popup is displayed, I click 'Authorize', then the FCM token eventually appears
- On Safari, I have created a desktop shortcut to force the activation of the Notification API (to be on the safe side). When I click on the shortcut to open the page
- the page is displayed
- no Authorization popup appears (which makes sense, since Notifications are already, de-facto enabled)
- in the Javascript console, plenty of red errors are displayed (see log below)
- clicking the 'Request permissions' immediately yields 'Authorization status: Authorized' in the top zone since Notification permission is de facto granted
- FCM token : the Circular progress indications spins forever.
Javascript console output (click to expand)
Error from backend:
Error: Bad state: Not connected to an application.
Stack Trace:
#0 DevHandler._handleConnection.<anonymous closure> (package:dwds/src/handlers/dev_handler.dart:272:13)
#1 _rootRunUnary (dart:async/zone.dart:1407:47)
#2 _CustomZone.runUnary (dart:async/zone.dart:1308:19)
#3 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1217:7)
#4 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:365:11)
#5 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:297:7)
#6 _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:123:11)
#7 _MapStream._handleData (dart:async/stream_pipe.dart:218:10)
#8 _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:153:13)
#9 _rootRunUnary (dart:async/zone.dart:1415:13)
#10 _CustomZone.runUnary (dart:async/zone.dart:1308:19)
#11 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1217:7)
#12 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:365:11)
#13 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:297:7)
#14 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:784:19)
#15 _StreamController._add (dart:async/stream_controller.dart:658:7)
#16 _StreamController.add (dart:async/stream_controller.dart:606:5)
#17 new WebSocketImpl.fromSocket.<anonymous closure> (package:web_socket_channel/src/copy/web_socket_impl.dart:730:21)
#18 _rootRunUnary (dart:async/zone.dart:1407:47)
#19 _CustomZone.runUnary (dart:async/zone.dart:1308:19)
#20 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1217:7)
#21 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:365:11)
#22 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:297:7)
#23 _SinkTransformerStreamSubscription._add (dart:async/stream_transformers.dart:63:11)
#24 _EventSinkWrapper.add (dart:async/stream_transformers.dart:13:11)
#25 _WebSocketProtocolTransformer._messageFrameEnd (package:web_socket_channel/src/copy/web_socket_impl.dart:319:23)
#26 _WebSocketProtocolTransformer.add (package:web_socket_channel/src/copy/web_socket_impl.dart:218:46)
#27 _SinkTransformerStreamSubscription._handleData (dart:async/stream_transformers.dart:111:24)
#28 _rootRunUnary (dart:async/zone.dart:1407:47)
#29 _CustomZone.runUnary (dart:async/zone.dart:1308:19)
#30 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1217:7)
#31 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:365:11)
#32 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:297:7)
#33 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:784:19)
#34 _StreamController._add (dart:async/stream_controller.dart:658:7)
#35 _StreamController.add (dart:async/stream_controller.dart:606:5)
#36 _Socket._onData (dart:io-patch/socket_patch.dart:2449:41)
#37 _rootRunUnary (dart:async/zone.dart:1415:13)
#38 _CustomZone.runUnary (dart:async/zone.dart:1308:19)
#39 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1217:7)
#40 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:365:11)
#41 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:297:7)
#42 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:784:19)
#43 _StreamController._add (dart:async/stream_controller.dart:658:7)
#44 _StreamController.add (dart:async/stream_controller.dart:606:5)
#45 new _RawSocket.<anonymous closure> (dart:io-patch/socket_patch.dart:1936:33)
#46 _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart:1379:14)
#47 _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
#48 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
#49 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:118:13)
#50 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:185:5)
@andynewman10 Thank you for reporting this issue. I've tested the example app found here: https://github.com/firebase/flutterfire/tree/master/packages/firebase_messaging/firebase_messaging/example, and I found that after clicking on request permissions and refreshing the page, it works without issues. Can you try and see if the example app works for you, or if you still face the same issue?
@TarekkMA how do you run the web page on Safari? Flutter for VS code cannot run or start a debug session on Safari, at least not directly. To test the page on Safari, I start a debug session on Chrome (with F5), which starts the development web server on, eg. http://localhost:45502. I then leave the page open in Chrome, and open the page separately with Safari.
Note that no matter how I test the page with Safari (requesting permissions then refreshing the page, like you ; or using a desktop shortcut to validate permissions beforehand, which I prefer to do), I get the same error.
The problem happens even if I change my locale to US english, system-wide.
I tried with Firefox and Chrome and, again, there is no issue with these browsers.
You can reproduce the issue with the example app by running the following command
flutter run --web-port 45502 -d web-server
Now test the page on Safari. Either just surf on the page then refresh it, or create a link on your desktop by dragging the URL from the browser address bar to the desktop.
The Javascript console with display the following errors
- Failed to load resource: the server responded with a status of 400 () - https://fcmregistrations.googleapis.com/v1/projects/flutterfire-e2e-tests/registrations
- Unhandled Promise Rejection: Error - throw core_patch.dart 265
Using Flutter 3.22.2, firebase_core 3.1.1, firebase_messaging 5.1.1.
In the Javascript console, if I click on https://fcmregistrations.googleapis.com/v1/projects/flutterfire-e2e-tests/registrations I get:
Request:
{"web":{"endpoint":"","auth":"","p256dh":"","applicationPubKey":"BNKkaUWxyP_yC_lki1kYazgca0TNhuzt2drsOrL6WrgGbqnMnr8ZMLzg_rSPDm6HKphABS0KzjPfSqCXHXEd06Y"}}
Response:
{
"error:" {
"code": 400,
"message": "Request contains an invalid argument.",
"status", "INVALID_ARGUMENT"
}
}
Full request headers:
:method: POST
:scheme: https
:authority: fcmregistrations.googleapis.com
:path: /v1/projects/flutterfire-e2e-tests/registrations
Accept: application/json
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en;q=0.9
Connection: keep-alive
Content-Length: 155
Content-Type: application/json
Host: fcmregistrations.googleapis.com
Origin: http://localhost:49555
Referer: http://localhost:49555/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15
x-goog-api-key: AIzaSyB7wZb2tO1-Fs6GbDADUSTs2Qs3w08Hovw
x-goog-firebase-installations-auth: FIS eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHBJZCI6IjE6NDA2MDk5Njk2NDk3OndlYjo4N2UyNWU1MWFmZTk4MmNkMzU3NGQwIiwiZXhwIjoxNzIxMTEzMjk2LCJmaWQiOiJkOEpKd0duZ1Yxd08wXzBTVmFCdl85IiwicHJvamVjdE51bWJlciI6NDA2MDk5Njk2NDk3fQ.AB2LPV8wRQIgHlR_4Fc5-U4Tno_hu29HTPX07VKSia4CtJEVwJ5rUs8CIQDYFRLfE_keKW8MF2SpESOu96vXy5ae3gH1aBODFu6ZhQ
I tried disabling CORS restrictions in Safari, didn't make any difference
I see a similar issue has been reported here:
https://github.com/firebase/firebase-js-sdk/issues/6620#issuecomment-2049382148
Thank you for the update
@TarekkMA Can I ask you what macOS version you are using? Are you by chance using macOS Sonoma?
Yes, and this is my macos version: 14.5 (23F79)
Thanks for your quick reply. @andreififiita, like me, is using macOS Ventura 13.6.x. I wonder if this detail plays a role in the problem we observe. We are both using Safari 17.4/17.5.
@TarekkMA @andynewman10 That is correct, i am using macOS Ventura 13.6.7. So we can confirm that this issue appears in Safari on macOS Sonoma as well? I am curious if anyone had managed to make it work properly on Sonoma.
@TarekkMA @andreififiita I suspect the problem might only affect Ventura. It would be a valuable piece of information for the firebase-js-sdk people to know if the problem is Ventura-related. Unfortunately I just have one Mac with Ventura, with no possibility to upgrade (MacBook A1708 from 2017).
@andynewman10 did you ever resolve this issue? I am having the exact same problem / error message when using ios devices :-( , and i can not find any solution :-(
I managed to trigger request permission popup by requesting it manually, trigger it on a button.
I have the same issue.
Flutter: 3.27.0 MacOS: Sequoia 15.1.1 (MacBook Air M2) Safari: 18.1.1
I've built my Flutter web project, placed it on the web server, and when I open the app in Safary, I get an exception while trying to obtain an FCM token.
[firebase_messaging/permission-blocked] Messaging: The notification permission was not granted and blocked instead.
The pop-up doesn't appear on the screen unlike in Chrome.
@sashker this is a separate issue.
Today, I tried again with Safari 18.2 for Ventura (released yesterday), with no luck.
I submitted a bug through the dedicated Safari user bugs website, about two or three weeks ago. Never got any news from Apple.
Symptoms described is like that one my work iPhone with iOS 26.0.1 but with ANY browser; Safari, Chrome or Edge.
Works fine on my private Pixel 7 Pro with Chrome. Works fine on my mac with macOS Tahoe 26.0.1 and Safari / Chrome Works fine on all windows machine tested
If I remove the integration-file "firebase-messaging-sw.js" page loads like before also on Safari.
// See this file for the latest firebase-js-sdk version:
// https://github.com/firebase/flutterfire/blob/main/packages/firebase_core/firebase_core_web/lib/src/firebase_sdk_version.dart
importScripts("https://www.gstatic.com/firebasejs/10.7.0/firebase-app-compat.js");
importScripts("https://www.gstatic.com/firebasejs/10.7.0/firebase-messaging-compat.js");
firebase.initializeApp({
apiKey: "xxx",
authDomain: "xxx",
databaseURL: "xxx",
projectId: "xxx",
storageBucket: "xxx",
messagingSenderId: "xxx",
appId: "xxx",
});
const messaging = firebase.messaging();
Optional:
messaging.onBackgroundMessage((message) => {
console.log("onBackgroundMessage", message);
});
Index.html only contains <script src="flutter_bootstrap.js" async></script> without the integration.
Could it be that the mobile version is running older modules that does not support notifications?
Edit: Work have policy that blocks all notifications from web browsers. Tested it with https://www.kenherbert.dev/browser-notification-tester/ says no on all browser on that phone. Co-workers who integrated into work (Intelligent Hub app) got the same policy too and got blocked notifications on all their browsers.
To get this working again for me I had to put the await FirebaseMessaging.instance.requestPermission(provisional: true, alert: true, badge: true); in a try/catch block and tell my app that notification is not supported.
Good to know if anyone stumble over this.