Firebase change credentials at run time from database
I’m working on a multi-organization Laravel application that uses Firebase Cloud Messaging (FCM) to send notifications. Each organization has its own FCM credentials because each organization's users use a separate app with a different SenderId.
I’m using the Firebase PHP SDK ("kreait/firebase-php": "6.3.1") and have overridden Laravel’s Notifiable trait to dynamically switch the FCM credentials at runtime, based on the organization associated with the user receiving the notification.
Here’s how I’ve implemented the custom trait:
Custom HasNotifiable Trait
// src\Domain\Auth\Models\Concerns\HasNotifiable.php
trait HasNotifiable
{
use Notifiable;
/**
* Send the given notification.
*
* @param mixed $instance
* @return void
*/
public function notify($instance)
{
$this->handleOrganizationNotification();
app(Dispatcher::class)->send($this, $instance);
}
/**
* Send the given notification immediately.
*
* @param mixed $instance
* @param array|null $channels
* @return void
*/
public function notifyNow($instance, array $channels = null)
{
$this->handleOrganizationNotification();
app(Dispatcher::class)->sendNow($this, $instance, $channels);
}
/**
* Custom method to handle organization-specific notification logic.
*
* @return void
*/
protected function handleOrganizationNotification()
{
try {
$organization = $this->getOrganization();
if ($organization && !is_null($organization->fcm_credentials)) {
Config::set('firebase.projects.app.credentials.file', $organization->fcm_credentials);
} else {
Config::set('firebase.projects.app.credentials.file', config('firebase.projects.app.credentials.fallback-file'));
}
} catch (\Exception $e) {
Log::error('Failed to set FCM credentials: '.$e->getMessage());
}
}
protected function getOrganization()
{
if (method_exists($this, 'organization') && $this instanceof User) {
return $this->organization;
}
if (method_exists($this, 'authable') && $this->authable instanceof User) {
return $this->authable?->organization;
}
return null;
}
}
Firebase Configuration
Here’s the relevant part of my Firebase configuration (config/firebase.php):
return [
'default' => env('FIREBASE_PROJECT', 'app'),
'projects' => [
'app' => [
'credentials' => [
'file' => env('FIREBASE_CREDENTIALS', env('GOOGLE_APPLICATION_CREDENTIALS')),
'fallback-file' => env('FIREBASE_CREDENTIALS', env('GOOGLE_APPLICATION_CREDENTIALS')),
],
],
],
];
User Model
In the User model, I’ve added the custom trait (HasNotifiable), along with others:
class User extends Authenticatable
{
use HasApiTokens, HasDevices, HasSocial, MobileActivation, SoftDeletes;
use HasConversations, HasDatabaseNotifications, HasFactory;
use HasNotifiable, HasSegment, HasOrganization;
}
Problem
Here’s the scenario:
- I have two organizations (
Org1andOrg2), each with its own FCM credentials (fcm_credentials) set in the database. - When I send a notification from
Org1, the first notification fails with an error:-
Unable to determine the Firebase Project ID - Sometimes, it also gives a
SenderId mismatcherror.
-
- The second notification from
Org1is sent successfully. - When
Org2sends a notification, the same issue happens—the first notification fails, and the second succeeds.
It seems like the first notification doesn’t correctly use the dynamic FCM credentials, but the second one does.
Question
What could be causing the issue where the first notification fails with a SenderId mismatch or Unable to determine the Firebase Project ID error, but subsequent notifications succeed? How can I ensure that the correct FCM credentials are used for each notification on the first attempt?
Notes:
- I’m using
Config::setto change the FCM credentials dynamically at runtime. - The issue appears to be related to switching between different FCM credentials for different organizations in the same process.
Please or to participate in this conversation.