Migrate from legacy HTTP to HTTP v1

Created on 3 August 2020, over 4 years ago
Updated 24 August 2023, about 1 year ago

Problem/Motivation

From Google: Apps using the FCM legacy HTTP API should consider migrating to the HTTP v1 API.

For more information:
* https://firebase.googleblog.com/2017/11/whats-new-with-fcm-customizing-m...
* https://firebase.google.com/docs/cloud-messaging/migrate-v1

Steps to reproduce

N/A

Proposed resolution

Migrate to the new HTTP v1 API following the guide provided by Google:
https://firebase.google.com/docs/cloud-messaging/migrate-v1

Remaining tasks

# Update the server endpoint used for sending messages (group management likely still needs to use the legacy endpoint)
# Update the authorization strategy to use OAuth bearer tokens
# Update the payload of send requests

User interface changes

None.

API changes

There may be changes needed to the service API for sending messages.

Data model changes

Not sure.

Feature request
Status

Active

Version

2.0

Component

Code

Created by

🇺🇸United States mediabounds

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • Migrate from legacy HTTP to HTTP v1 patch

  • Update PATCH file.
    Migrate from legacy HTTP to HTTP v1 patch

  • Update PATCH file.
    Migrate from legacy HTTP to HTTP v1 patch

  • 🇳🇱Netherlands mieg Amsterdam

    hi SiarheiNik, i tried to use your patch but i couldn't get it to work. It seems there is now a dependency on google-auth-library-php? I get this error:

    Error Class "Google\Auth\ApplicationDefaultCredentials" not found.

  • 🇭🇺Hungary gazsesz

    Hi,
    Can we expect an update to version 3.0.1 ?

  • Update the configuration form. Added file selection for credentials. The file is saved to the private folder 'file_private_path'

  • 🇦🇹Austria drupalfan2

    I recently got this reminder from google:

    [Reminder] Update your apps to the latest Firebase Cloud Messaging APIs and SDKs

    We’re writing to remind you that starting June 20, 2024 the legacy Firebase Cloud Messaging (FCM) APIs will be discontinued.

    On June 20, 2024, we’re reducing the number of Firebase Cloud Messaging (FCM) legacy register APIs and legacy send APIs that provide similar functionality. This step will allow us to provide you with a more consistent experience and align with Google security standards to improve security, reliability and performance.

    Because of these API decommissions, some already-deprecated SDKs and features will stop working after June 20, 2024.

    What do you need to do?
    Take the following actions before June 20, 2024, to ensure that you have access to the latest supported features and to reduce the risk of future decommissions affecting your usage:
    •Follow the instructions described in Firebase FAQ to migrate your individual APIs.
    •Update to the latest versions of Firebase SDKs:

    Android >= 23.1.2
    iOS >= 10.10.0
    Web (Javascript) >= 9.22.1

    Your Firebase project(s) that use Firebase Cloud Messaging APIs are listed below:
    ◦Your recent usage of impacted APIs/features: Legacy HTTP protocol
    ◦Your recent usage of impacted APIs/features: Server Keys

    Will this patch provide the needed actions?
    Will this patch update the "Legacy HTTP protocol" and also the "Server Keys" topic?
    Will this patch change over to the latest api versions?

    Thank you.

  • 🇸🇪Sweden deadbeef

    Here's an update which fixes among other things:

    • Allows Google credentials path to be set in the environment through $_ENV or otherwise ( credentials files inside the webroot aren't really desirable ).
    • Fixes sendToTopic() to use the condition field if topics field is not set
    • Fixes the jsonSerialize function declaration of FCMOptions to return array and avoid warning
    • Misc coding standards fixes.
  • 🇯🇵Japan ptmkenny

    @deadbeef Please do not combine changes that are not directly related to an issue in a patch; this will result in the patch being rejected.

    Patches need to be reviewed, and it is much easier to review a patch when it is only trying to do one thing. Also, there are already separate issues for coding standards and the array declaration.

  • Status changed to Needs work 7 months ago
  • 🇸🇪Sweden deadbeef

    @ptmkenny If it's ok with @SiarheiNik I will refactor using config as soon as I get time and try to keep the interface as close to the legacy module as possible. We just needed this to work like yesterday with our credentials policy.

    Another thing to discuss is whether typing the various Android/iOS bits and pieces adds enough value. The message itself is a simple, well-documented JSON string and just building it and sending it is very easy to just template, rather than instantiating loads of objects to later then just simply render it out anyway.

  • 🇯🇵Japan ptmkenny

    @deadbeef Thank you for the additional information.

    Another thing to discuss is whether typing the various Android/iOS bits and pieces adds enough value. The message itself is a simple, well-documented JSON string and just building it and sending it is very easy to just template, rather than instantiating loads of objects to later then just simply render it out anyway.

    I think it would be better to build the string than to instantiate lots of objects; this API migration makes the code more complex, so I think we should try to keep it as simple as possible.

  • 🇯🇵Japan ptmkenny

    @deadbeef Interesting. As you suggest, it might make more sense to make a wrapper around that package than to rework the code in this module when that package has already done the work.

    At the same time, the big problem is this issue was opened three years ago and never got a single comment from any of the listed maintainers, so if such a wrapper was going to be written, it might be better as a new module than as a new major version of this one, since this module is effectively unmaintained.

    I emailed @thalles, the last maintainer to commit to this module, on April 11 but haven't heard back.

  • 🇧🇷Brazil leopaccanaro

    Hello @ptmkenny.

    Unfortunately I am focused more on Java projects and with a special daughter. Sorry to hear @thalles and @renatog are not active around here.
    I know Renato and I will talk to him later. I think is on vacation right now.
    In the mean time, any of you want to maintain the module? Let me know.

  • 🇯🇵Japan ptmkenny

    @leopaccanaro Thank you for the response.

    As suggested by @deadbeef, firebase-php does 90% of what we want to do already, so it makes sense to use that going forward.

    To explore this option, I am currently working on https://www.drupal.org/project/firebase_php .

  • 🇧🇪Belgium waropd

    Pending an update on https://www.drupal.org/project/firebase_php I'm currently using the patch.
    When using firebase in config split and removing the credentials_path locally in the settings, the upload works but the json credentials file isn't saved to the field anymore.

    Remove the logger and give the option to return NULL.

  • 🇧🇪Belgium waropd

    Include new entities in patch.

  • 🇷🇴Romania rares petru samartean

    Perhaps this is not proper reporting but I should mention it.

    The google credentials file does not stay set properly. I added it in the configuration form, the form saved properly and I could see it saved.
    After a bit of time I noticed I was no longer getting notifications from my local env, even though I was getting them before.
    I went to check the form and saw that a different, random PNG file was assigned instead of the credentials file.
    I readded it and moved on.
    After a while, again, instead of being reassinged randomly, it got deleted completely and was no longer appearing as set in the form.

    I haven't looked into why it happens yet. I used the v10 patch from #13.
    Also, setting the config value programatically using something like

    $settings['firebase.settings']['credentials_path'] = 'private://firebase/inkjin-e4091-84c8a56e2a6c.json';
    

    doesn't seem to work, or it at least doesn't get recognised in the form. I don't know which one exactly yet as I'm pretty overwhelmed.

    Hope this helps you guys. I'll post a fix if I ever find the time to I hope.

  • 🇷🇴Romania rares petru samartean

    Hi again. I'm not sure about setting the path using settings.php since it's not actually a path but a file ID, but I still think I found the issue.

    The generated file was being set as temporary. What I did was loading the file by ID in the submit handler of the configuration form, setting it as permanent, then saving it, then setting the file id as the credentials_path config.

    Hope this helps. I can't contribute code from my workplace but that should be good enough for you guys to have at it. Thank you for your contributions!

  • Hello Team.

    I also need to fix the module, Can you let me know if I need to apply all patches or only the last one?

  • Thank you! I have applied the latest patch in #24 and i have succesfully uploaded the file with the credentials.
    However, this broke the functionality and it doesn't send notifications anymore. The code I use is similar to the modules documentation:

    // Token is generated by app. You'll have to send the token to Drupal.
    $fakeToken = 'e3vUiwcvkpY:APA91bEDZzKTIkaL0e-UTwiV6EGi1m5J5PrDMxejm6-d85vdwAgd';
    $messageService = \Drupal::service('firebase.message');
    $messageService->setRecipients($fakeToken);
    $messageService->setNotification([
      'title' => 'Title goes here',
      'body' => 'Body goes here',
      'badge' => 1,
      'icon' => 'optional-icon',
      'sound' => 'optional-sound',
      'click_action' => 'optional-action',
    ]);
    $messageService->setData([
      'score' => '3x1',
      'date' => '2017-10-10',
      'optional' => 'Data is used to send silent pushes. Otherwise, optional.',
    ]);
    $messageService->setOptions(['priority' => 'normal']);
    $messageService->send();
    

    It seems that the setNotification does not exist anymore and I am not sure what other changes are done.

    Could someone provide me with an example (instructions/code) on how to send a notification after applying the patch?

  • Should like this:

     /** @var FirebaseMessageService $messageService */
     $messageService = \Drupal::service('firebase.message');
     $messageService->setRecipients($fcmToken);
     // Notification
     $notification = new Notification('Title goes here');
     $notification->setBody('Body goes here');
     // Message data
     $messageData = MessageData::fromArray([
      'score' => '3x1',
      'date' => '2017-10-10',
      'optional' => 'Data is used to send silent pushes. Otherwise, optional.',
    ]);
     // Message
     $message = new Message($notification);
     $message->setData($messageData);
     $messageService->setMessage($message);
     // Android config
     $android_config = new AndroidConfig();
     $android_config->setPriority('high');
     $message->setAndroidConfig($android_config);
     // Apple config
     $apns_config = new ApnsConfig();
     $apns_config->setHeaders(['apns-priority' => '5']);
     $apns_config->setPayload([
          'aps'=> [
            'mutable-content' => 1,
            'content-available' => 1
          ]
        ]);
    $message->setApnsConfig($apns_config);
    
    $result = $messageService->sendToTokens();
  • 🇺🇦Ukraine spheresh

    The credentials path contains the id file. This can become a problem when migrating configs as for me.

    This is an initial solution that uses the key module, which works well with http-v1
    https://git.drupalcode.org/issue/firebase-3163053/-/tree/http-v1

    The only problem is that GOOGLE_APPLICATION_CREDENTIALS requires a file path.

    That's why

    '#type' => 'key_select',
    '#key_filters' => ['provider' => 'file'],

    We can only use the file provider.
    I have added a @todo to research if we can use $key_entity->getKeyValue() instead.

    Because the patch does not allow you to use all the functionality of the keys module for now.

  • Tri Tran thank you for your code!

    I am now receiving the following error: "Failure code: 403; Failure status: PERMISSION_DENIED; Failure message: Permission 'cloudmessaging.messages.create' denied on resource '//cloudresourcemanager.googleapis.com/projects/MYPROJECTNAME' (or it may not exist)."

    Any ideas?

  • 🇧🇪Belgium waropd

    Extension of patch #23
    Set uploaded file to permanent

  • 🇧🇬Bulgaria Ana Bozhilova

    Hi,

    I have installed the latest patch and updated my code accordingly. I have also inserted the JSON file into the module configuration. However, I encountered an issue:

    Error: Class "Google\Auth\ApplicationDefaultCredentials" not found in Drupal\firebase\Service\FirebaseServiceBase->getHandler()

    Below is the updated code I am using:

    <strong>I have installed the latest patch . </strong>
    I have change my code to be :
    
    /** @var FirebaseMessageService $messageService */
      $messageService = \Drupal::service('firebase.message');
      $messageService->setTopics($topic);
    
      // Notification
      $notification = new Notification($val['title']);
      $notification->setBody($val['body']);
    
      // Message data
      $messageData = MessageData::fromArray([
        'type' => 'axp-content',
        'url'  => $val['url'],
      ]);
    
      // Message
      $message = new Message($notification);
      $message->setData($messageData);
      $messageService->setMessage($message);
    
      // Android config
      $android_config = new AndroidConfig();
      $android_config->setPriority('normal');
      $message->setAndroidConfig($android_config);
    
      // Apple config
      $apns_config = new ApnsConfig();
      $apns_config->setHeaders(['apns-priority' => '5']);
      $apns_config->setPayload([
        'aps' => [
          'mutable-content' => 1,
          'content-available' => 1
        ]
      ]);
      $message->setApnsConfig($apns_config);
    
      try {
        $messageService->sendToTopic();
      
      } catch (Exception $e) {
        $error = 'Push-Message failed: ' . $val['title'] . ' - ' . $val['body'] . ' URL: ' . $val['url'] . ' Error: ' . $e->getMessage();
        
      }
  • 🇧🇬Bulgaria Ana Bozhilova

    Hi,
    I have installed the latest patch and updated my code accordingly. I have also inserted the JSON file into the module configuration. However, I encountered an issue:
    Error: Class "Google\Auth\ApplicationDefaultCredentials" not found in Drupal\firebase\Service\FirebaseServiceBase->getHandler()

    The code I am using before the changes:

    $messageService = Drupal::service('firebase.message');
      $messageService->setTopics($topic);
      $messageService->setNotification([
        'title' => $val['title'],
        'body'  => $val['body'],
        //    'badge' => 1,
        //    'icon'         => 'optional-icon',
        'sound' => 'default',
        //    'click_action' => 'optional-action',
      ]);
      $messageService->setData([
        'type' => 'axp-content', // default 'axp-content'
        'url'  => $val['url'], // zb '/axp/node/13'
      ]);
      $messageService->setOptions(['priority' => 'normal']);
    
      try {
        $messageService->send();
     
      } catch (Exception $e) {
        $error = 'Push-Message failed: ' . $val['title'] . ' - ' . $val['body'] . ' URL: ' . $val['url'] . ' Error: ' . $e->getMessage();
    
      }

    Below is the updated code I am using:
    I have installed the latest patch . I have change my code to be

    /** @var FirebaseMessageService $messageService */
      $messageService = \Drupal::service('firebase.message');
      $messageService->setTopics($topic);
    
      // Notification
      $notification = new Notification($val['title']);
      $notification->setBody($val['body']);
    
      // Message data
      $messageData = MessageData::fromArray([
        'type' => 'axp-content',
        'url'  => $val['url'],
      ]);
    
      // Message
      $message = new Message($notification);
      $message->setData($messageData);
      $messageService->setMessage($message);
    
      // Android config
      $android_config = new AndroidConfig();
      $android_config->setPriority('normal');
      $message->setAndroidConfig($android_config);
    
      // Apple config
      $apns_config = new ApnsConfig();
      $apns_config->setHeaders(['apns-priority' => '5']);
      $apns_config->setPayload([
        'aps' => [
          'mutable-content' => 1,
          'content-available' => 1
        ]
      ]);
      $message->setApnsConfig($apns_config);
    
      try {
        $messageService->sendToTopic();
       
      } catch (Exception $e) {
        $error = 'Push-Message failed: ' . $val['title'] . ' - ' . $val['body'] . ' URL: ' . $val['url'] . ' Error: ' . $e->getMessage();
        
      }

    if I use $result = $messageService->sendToTokens() i got another eror. -> The message should contain target!
    Another message. : Deprecated function
    : Return type of Drupal\firebase\Entity\MessageData::jsonSerialize() should either be compatible with JsonSerializable::jsonSerialize(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in

    Structure of json file

    type
    project_id	
    private_key_id
    private_key
    client_email
    client_id
    auth_uri
    token_uri
    auth_provider_x509_cert_url
    client_x509_cert_url
    universe_domain	
    
  • Hi everyone,
    I have installed the latest patch (#32) and updated the new configuration page accordingly.
    I've uploaded a .json file which I was given from the Firebase, but it's not working.

    Here is the structure of the .json file I received:

    type
    project_id
    private_key_id
    private_key
    client_email
    client_id
    auth_uri
    token_uri
    auth_provider_x509_cert_url
    client_x509_cert_url
    universe_domain

    For the "Project ID" field in the "Firebase Push Notification Configuration" page, I've used the "project_id" from the .json file.
    For "Credentials" field, I have uploaded the provided .json file.

    The old code is:

    function _eutb_firebase_push_message($topic, $val) {
      /** @var FirebaseMessageService $messageService */
      $messageService = \Drupal::service('firebase.message');
      $messageService->setTopics($topic);
    
      // Notification
      $notification = new Notification($val['title']);
      $notification->setBody($val['body']);
    
      // Message data
      $messageData = MessageData::fromArray([
        'type' => 'axp-content',
        'url'  => $val['url'],
      ]);
    
      // Message
      $message = new Message($notification);
      $message->setData($messageData);
      $messageService->setMessage($message);
    
      // Android config
      $android_config = new AndroidConfig();
      $android_config->setPriority('normal');
      $message->setAndroidConfig($android_config);
    
      // Apple config
      $apns_config = new ApnsConfig();
      $apns_config->setHeaders(['apns-priority' => '5']);
      $apns_config->setPayload([
        'aps' => [
          'mutable-content' => 1,
          'content-available' => 1
        ]
      ]);
      $message->setApnsConfig($apns_config);
    
      try {
        $messageService->sendToTopic();
        }
      } catch (Exception $e) {
        $error = 'Push-Message failed: ' . $val['title'] . ' - ' . $val['body'] . ' URL: ' . $val['url'] . ' Error: ' . $e->getMessage();
      }
    }

    The new code is:

    /** @var FirebaseMessageService $messageService */
      $messageService = \Drupal::service('firebase.message');
      $messageService->setTopics($topic);
    
      // Notification
      $notification = new Notification($val['title']);
      $notification->setBody($val['body']);
    
      // Message data
      $messageData = MessageData::fromArray([
        'type' => 'axp-content',
        'url'  => $val['url'],
      ]);
    
      // Message
      $message = new Message($notification);
      $message->setData($messageData);
      $messageService->setMessage($message);
    
      // Android config
      $android_config = new AndroidConfig();
      $android_config->setPriority('normal');
      $message->setAndroidConfig($android_config);
    
      // Apple config
      $apns_config = new ApnsConfig();
      $apns_config->setHeaders(['apns-priority' => '5']);
      $apns_config->setPayload([
        'aps' => [
          'mutable-content' => 1,
          'content-available' => 1
        ]
      ]);
      $message->setApnsConfig($apns_config);
    
      try {
        $messageService->sendToTopic();
      
      } catch (Exception $e) {
        $error = 'Push-Message failed: ' . $val['title'] . ' - ' . $val['body'] . ' URL: ' . $val['url'] . ' Error: ' . $e->getMessage();
      }

    After I try to send a push message, I get this error:
    Error: Class "Google\Auth\ApplicationDefaultCredentials" not found in Drupal\firebase\Service\FirebaseServiceBase->getHandler()

    I saw that mieg (#8) reported the same issue, but this dependancy is already integrated in the latest patch and I have it locally and on my DEV system, but it still complains about it.
    Does anyone can help with ideas what might be wrong?

    I also tried the example from Tri Tran (#29) with the $messageService->sendToTokens();, but then I have another error: Error: The message should contain target.

    Any ideas/thoughts would be highly appreciated!

    Regards,
    Daniela

  • 🇧🇬Bulgaria Ana Bozhilova

    Hi,
    Install "google/cloud-firestore": "^0.1.0"

  • 🇧🇬Bulgaria Ana Bozhilova

    Hi,
    Here is and a fix for this warning from patch 31

    Deprecated function: Return type of Drupal\firebase\Entity\MessageData::jsonSerialize() should either be compatible with JsonSerializable::jsonSerialize(): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in include()

  • Hi Ana Bozhilova,

    thanks for your response. Installing "google/cloud-firestore" and applying your latest patch worked for me.
    The push messages are sent without any errors.

  • Thank you to everyone involved in the successive patches, I can confirm I was able to have notifications working again in my Drupal web app, though not with some work.

    A few tips for other people struggling with this:

    - After you apply the #38 patch to the latest 3.0.1 version, don't forget to run drush updb or update.php to get all the changes to the module's configuration in the db.

    - The credentials json is found not on the firebase console like usual but on the google cloud console, search for "google service account credentials json"

    - This might be obvious, but don't forget to import the needed classes at the top of your file:

    use Drupal\firebase\Entity\Message;
    use Drupal\firebase\Entity\MessageData;
    use Drupal\firebase\Entity\Notification;
    use Drupal\firebase\Entity\AndroidConfig;
    use Drupal\firebase\Entity\ApnsConfig;

    - This is the code that I'm using at the moment:

    public static function firebase_message($token, $title, $body, $data)
        {
            $service = Drupal::service('firebase.message');
            $service->setRecipients($token);
            
            $notification = new Notification($title);
            $notification->setBody($body);
            
            $data = MessageData::fromArray($data);
              
            // Message
             $message = new Message($notification);
             $message->setData($data);
             $service->setMessage($message);
             // Android config
             $android_config = new AndroidConfig();
             $android_config->setPriority('high');
             $message->setAndroidConfig($android_config);
             // Apple config
             $apns_config = new ApnsConfig();
             $apns_config->setHeaders(['apns-priority' => '5']);
             $apns_config->setPayload(['aps'=> ['mutable-content' => 1, 'content-available' => 1]]);
             $message->setApnsConfig($apns_config);
            
              $result = $service->sendToTokens();
        }
    

    Regards.

  • 🇳🇱Netherlands mieg Amsterdam

    Did anybody succeed in sending data-only messages with the latest patches? I couldn't find a way to send a message without a notification.

  • Anyone has implemented sendMulticast() method to send common notification to multiple devices or any reference?

    https://firebase-php.readthedocs.io/en/7.16.0/cloud-messaging.html#send-...

Production build 0.71.5 2024