FCM SendAllAsync not working with Google Application Default Credentials
See original GitHub issueEnvironment
- Operating System version: Mac OS Catalina (10.15.7)
- Firebase SDK version: 2.0.0
- Firebase Product: Firebase Cloud Messaging
- .NET version: .NET Core 3.1
- OS: Mac
The problem
We’re developing a .NET Core API for a new mobile applicatione. One of the features is sending Push Notifications from the API. To make connection with all our Google Services and Firebase Cloud Messaging we’re making use of APPLICATION DEFAULT CREDENTIALS. This is not done via a environment variable but with logging in with following command.
gcloud auth application-default login
When doing the initial setup we encountered a problem that had the following error message.
FirebaseAdmin.Messaging.FirebaseMessagingException:
Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the fcm.googleapis.com.
We recommend configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting.
For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.
Eventually this problem was resolved by setting the billing/quota_project in my config by running following command.
gcloud auth application-default set-quota-project my-project
Sending single push notifications was no problem and everything was implemented very quickly.
Now we were up to sending push notifications to a batch of devices (tokens). Therefore we are using the method SendMulticastAsync to send a single message to different devices, underlying this method is using SendAllAsync.
When we implemented this in our API we noticed that none of the messages was sent. When digging a bit deeper we saw that the reason for this was following error which is the same as we encountered during setup. The strange thing is that the single notification is still working.
FirebaseAdmin.Messaging.FirebaseMessagingException:
Your application has authenticated using end user credentials from the Google Cloud SDK or Google Cloud Shell which are not supported by the fcm.googleapis.com.
We recommend configuring the billing/quota_project setting in gcloud or using a service account through the auth/impersonate_service_account setting.
For more information about service accounts and how to use them in your application, see https://cloud.google.com/docs/authentication/.
I already pulled my hair out finding the solution for this but after hours of searching didn’t came up with a solution. No idea if I’m doing something wrong or there’s some bug. But I do hope you guys can help out 😃
Relevant Code:
// Startup.cs
FirebaseApp.Create(new AppOptions
{
Credential = GoogleCredential.GetApplicationDefault(),
ProjectId = configuration.GetValue<string>("Firebase:ProjectId")
});
// Implementation
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FirebaseAdmin.Messaging;
using MyProject.Domain.CloudMessaging;
namespace MyProject.Infrastructure.Firebase
{
public class CloudMessagingService : ICloudMessagingService
{
public async Task SendSingleNotification(NotificationData notificationData, string token)
{
if (token == null)
{
return;
}
var message = CreateMessage(notificationData, token);
try
{
await FirebaseMessaging.DefaultInstance.SendAsync(message);
}
catch (Exception e)
{
Console.Write(e);
}
}
public async Task SendMultipleNotifications(NotificationData notificationData, List<string> tokens)
{
if (tokens.Count == 0)
{
return;
}
var message = CreateMulticastMessage(notificationData, tokens);
try
{
var response = await FirebaseMessaging.DefaultInstance.SendMulticastAsync(message);
Console.WriteLine($"{response.SuccessCount} messages were sent successfully");
}
catch (Exception e)
{
Console.Write(e);
}
}
private Message CreateMessage(NotificationData notificationData, string token)
{
var message = new Message
{
Notification = new Notification
{
Title = notificationData.Title,
Body = notificationData.Body
},
Data = notificationData.Data,
Token = token,
FcmOptions = new FcmOptions
{
AnalyticsLabel = notificationData.AnalyticsLabel.ToString()
}
};
return message;
}
private MulticastMessage CreateMulticastMessage(NotificationData notificationData, IReadOnlyList<string> tokens)
{
var message = new MulticastMessage
{
Notification = new Notification
{
Title = notificationData.Title,
Body = notificationData.Body
},
Data = notificationData.Data,
Tokens = tokens
};
return message;
}
}
}
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (1 by maintainers)
Top Related StackOverflow Question
@DamienDoumer thank you for your advice regarding how to send messages to several users, will definitely take a look into that! Much appreciated!
Just wondering then in which case(s) the method
SendMulticastAsyncshould be used then?Just catching up to this issue. Here are my thoughts on this:
GOOGLE_APPLICATION_CREDENTIALSenvironment variable to get app default credentials working locally (see https://firebase.google.com/docs/admin/setup#initialize-sdk).Update: Also note that for this use case to work as intended, you might have to set the quota project on the
GoogleCredentialobject it self. See https://github.com/googleapis/google-api-dotnet-client/blob/master/Src/Support/Google.Apis.Auth/OAuth2/GoogleCredential.cs#L296-L307