Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Getting wrong fcm token in IOS #8697

Open
pavelustenko opened this issue Jan 9, 2025 · 6 comments
Open

Getting wrong fcm token in IOS #8697

pavelustenko opened this issue Jan 9, 2025 · 6 comments

Comments

@pavelustenko
Copy link

pavelustenko commented Jan 9, 2025

Operating System

IOS 18

Environment (if applicable)

Safari

Firebase SDK Version

11.1.0

Firebase SDK Product(s)

Messaging

Project Tooling

React Application. webpack

Detailed Problem Description

My PWA is deployed to /web-pwa context path on my server and it does not receive notification in IOS (Android works fine) presumably because of getting a wrong token when worker scope is dffer from default '/'

Steps and code to reproduce issue

App.js

import {initializeApp} from "firebase/app";
import {getMessaging, getToken} from "firebase/messaging";

const firebaseConfig = {
    apiKey: "...",
    authDomain: "...",
    databaseURL: "...",
    projectId: "...",
    storageBucket: "...",
    messagingSenderId: "...",
    appId: "...",
    measurementId: "..."
};

export default class App extends React.Component{

init = ()=>{
        if ('serviceWorker' in navigator) {
            if ('Notification' in window) {
         Notification.requestPermission().then((permission) =>{
            if (permission === 'granted') {
                this.registerWorkers();
            }
          }).catch(function(error) {
           console.log('error:', error);
          });
            }
    }

    registerWorkers = () => {
        let r;
        navigator.serviceWorker.register('/web-pwa/firebase-messaging-sw.js', {scope: '/web-pwa/'})
            .then(swRegistration => {
                console.log('Service Worker is registered for scope '+swRegistration.scope);
                r = swRegistration;
                console.log(swRegistration.scope);
                    return navigator.serviceWorker.ready;
            }).then(registration=>{
            console.log('Service Worker is '+ (registration.active?'active':'inactive') + ' for scope:' + registration.scope);

            return registration.pushManager.subscribe({
                      userVisibleOnly: true,
                      applicationServerKey: urlBase64ToUint8Array('...my-vapid-key...')
                    });
            })
            .then(subscription => {
                this.logString('web-push-subscription:'+ JSON.stringify(subscription.toJSON()));
                if(!this.state.fcmToken) {
                    getToken(messaging, {
                        serviceWorkerRegistration: r,
                    }).then(token => {
                       console.log('got FCM: '+ token);
                        this.setState({fcmToken: token});
                    }).catch(error => {
                        console.error('Error getting token:', error.message);
                    });
                }else{
                    this.logString('FCM is already present')
                }
            })
            .catch(error => {
                console.error('Service Worker registration failed:', error);
            });
        console.log('navigator.serviceWorker.addEventListener')
    }
render(){
return(
<div className="App">
<button onClick={this.init}>initialize</button>
<input type='text' value='{this.state.fcmToken}'/>
</div>
);
}
}

function urlBase64ToUint8Array (base64String){
    const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
    const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');

    const rawData = window.atob(base64);
    const outputArray = new Uint8Array(rawData.length);

    for (let i = 0; i < rawData.length; ++i) {
        outputArray[i] = rawData.charCodeAt(i);
    }

    return outputArray;
};

firebase-messaging-sw.js

importScripts('https://www.gstatic.com/firebasejs/11.1.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/11.1.0/firebase-messaging-compat.js');

const firebaseConfig = {
  apiKey: "...",
  authDomain: "...",
  databaseURL: "...",
  projectId: "...",
  storageBucket: "...",
  messagingSenderId: "...",
  appId: "...",
  measurementId: "..."
};

firebase.initializeApp(firebaseConfig);

// Retrieve firebase messaging
const messaging = firebase.messaging();



self.addEventListener('push', function(event) {

  event.waitUntil(
      self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function(clientList) {
        if (clientList.length > 0) {
          clientList.forEach(client=>{
            client.postMessage({type: 'push', data: {}});
          });
        }else{
          self.clients.openWindow('/web-pwa/').then(function(client) {
            client.postMessage({type: 'push', data: {}});
          });
        }
      })
  );

  let notificationTitle = 'test';
  let notificationOptions = {
    body: 'hello',
  }
  try {
    let payload = event.data.json();
    console.log('push with payload', payload);
    notificationTitle = payload.data.id;
    notificationOptions = {
      body: payload.data.messageId,
      data: {...payload.data}
    };
  }catch (e){
    console.log(e);
  }

  event.waitUntil(
      self.registration.showNotification(notificationTitle+'-push', notificationOptions)
  );
});



self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  event.waitUntil(
      self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function(clientList) {
        if (clientList.length > 0) {
          let client = clientList[0];
          client.focus();
          client.postMessage({type: 'notificationPressed', data: event.notification.data});
        }else{
           self.clients.openWindow('/web-pwa/').then(function(client) {
              client.postMessage({type: 'notificationPressed', data: event.notification.data});
        });
        }
      })
  );
});

When I press 'initialize' button in PWA installed on real devices (Android phone and iPhone) I'm getting a FCM token successfully. But when I send test notifications from firebase console using tokens I got from apps, Android is showing notifications as expected, but no luck in IOS.

@pavelustenko pavelustenko added new A new issue that hasn't be categoirzed as question, bug or feature request question labels Jan 9, 2025
@google-oss-bot
Copy link
Contributor

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

@jbalidiong jbalidiong added api: messaging needs-attention and removed needs-triage new A new issue that hasn't be categoirzed as question, bug or feature request labels Jan 9, 2025
@dlarocque
Copy link
Contributor

Hi @pavelustenko, can you confirm whether in an iOS PWA:

  1. The service worker is registered and active
  2. The registration of the custom service worker is successful
  3. The 'push' event listener is triggered

Also, to help us isolate the issue, can you confirm that this works if you register the service worker at the default scope?

@pavelustenko
Copy link
Author

pavelustenko commented Jan 10, 2025

Hi, @dlarocque ,
I can confirm that worker is registered and active. I've implemented a simple message exchange between service worker and main app, and it works as expected.
The registration is successful because I finally managed to get a token. getToken cannot work without a regitered service-worker.
Push event does not fire in Safari (IOS and MacOS), but it does fire in Chrome on all platforms and in Android as PWA.

I will check a default scope configuration in few days.

@bangluong
Copy link

Hi, I got stuck while get token on safari. how can you get it?
it seem indexDB is disable, but I dont know to check it

@dlarocque
Copy link
Contributor

Hi, @dlarocque , I can confirm that worker is registered and active. I've implemented a simple message exchange between service worker and main app, and it works as expected. The registration is successful because I finally managed to get a token. getToken cannot work without a regitered service-worker. Push event does not fire in Safari (IOS and MacOS), but it does fire in Chrome on all platforms and in Android as PWA.

I will check a default scope configuration in few days.

That's all very useful to know, thanks!

You mentioned that the events aren't triggered on Safari iOS and macOS- is this on PWAs only?

@google-oss-bot
Copy link
Contributor

Hey @pavelustenko. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants