Search code examples
firebasereact-nativepush-notificationfirebase-cloud-messagingreact-native-fcm

What marks Firebase Cloud Messaging tokens as inactive?


I am having trouble finding the correct informations in the documentations or firebase.

When stale tokens reach 270 days of inactivity, FCM will consider them expired tokens

What defines inactivity ?

If an app calls getToken(), will this reset the counter to 0 days ?

If an app didn't call getToken() for 200 days and receives a push notification, will this reset the counter to 0 days ?

I need this information in order to know when to update the timestamp in our backend.

It's very difficult to test since you can't really know what the real expiry date is for the token and you can't wait 270 days just to figure it out.


Solution

  • Instead of proactively trying to remove tokens from your database, you can (and actually should) depend on the FCM API response to detect outdated and invalid tokens. From the documentation on detecting invalid tokens:

    Detect invalid token responses from the FCM backend
    Make sure to detect invalid token responses from FCM and respond by deleting from your system any registration tokens that are known to be invalid or have expired. With the HTTP v1 API, these error messages may indicate that your send request targeted invalid or expired tokens:

    • UNREGISTERED (HTTP 404)
    • INVALID_ARGUMENT (HTTP 400)

    Note: `INVALID_ARGUMENT1 can also be returned in cases of issues in the message payload, so it signals an invalid token only if the payload is completely valid. See ErrorCodes for more information.

    If you are certain that the message payload is valid and you receive either of these responses for a targeted token, it is safe to delete your record of this token, since it will never again be valid. For example, to delete invalid tokens from Cloud Firestore, you could deploy and run a function like the following:

    // Registration token comes from the client FCM SDKs
    const registrationToken = 'YOUR_REGISTRATION_TOKEN';
    
    const message = {
      data: {
        // Information you want to send inside of notification
      },
      token: registrationToken
    };
    
    // Send message to device with provided registration token
    getMessaging().send(message)
    .then((response) => {
        // Response is a message ID string.
    })
    .catch((error) => {
        // Delete token for user if error code is UNREGISTERED or INVALID_ARGUMENT.
        if (errorCode == "messaging/registration-token-not-registered") {
            // If you're running your own server, call API to delete the
            token for the user
    
            // Example shown below with Firestore
            // Get user ID from Firebase Auth or your own server
           Firebase.firestore.collection("fcmTokens").document(user.uid).delete()
        }
    });
    

    FCM will only return an invalid token response if a token expired after 270 days or if a client explicitly unregistered. If you need to more accurately track staleness according to your own definitions, you can proactively remove stale registration tokens.

    That last link is what you seem to be trying to do, so from that (emphasis mine):

    Maintain token freshness and remove stale tokens
    Determining whether a token is fresh or stale is not always straightforward. To cover all cases, you should adopt a threshold for when you consider tokens stale. By default, FCM considers a token to be stale if its app instance hasn't connected for a month. Any token older than one month is likely to be an inactive device; an active device would have otherwise refreshed its token.

    Depending on your use case, one month may be too short or too long, so it is up to you to determine the criteria that works for you.

    So if you also implement this token cleanup, you should remove any token that's older than a month as an active client will have refreshed its token by then.