When do GCM Tokens Expire and What is the InstanceID?

15.4k views Asked by At

Since GCM keeps getting updated, most of the resources I have searched seem outdated or unclear. Basically, I am confused over when the tokens and ID's expire. (For reference, I am working with Android.)

From what I understand (and please correct me if I'm wrong), my server has an API Key and a Sender ID. Using the Sender ID I can have my client request a Token via the InstanceID stored locally on my client. I'm already a bit confused here. The InstanceID is assigned the moment my app goes online? Does it ever change? What about when the app upgrades or is uninstalled and reinstalled (or the device is restored)? By calling InstanceID.getInstance will I always retrieve the same InstanceID, or will it eventually expire and give me a new one? Is there any value to storing the string you retrieve by calling getID()? The docs seem to indicate that you actually retrieve a new InstanceID when you call getID(), so that complicates things even more. (For reference, I'm referring to: https://developers.google.com/instance-id/)

Using the InstanceID, my client can request a Token from the GCM servers, which it then sends to my app server. My app server stores this Token, and can use this to send messages to the GCM servers, which will then send the message to the device. The device uses the stored InstanceID to actually receive these messages, I believe. So having a class that extends GcmListenerService will allow me to receive these messages with onMessageReceived? I don't have to do anything special (other than defining it in the AndroidManifest)? I don't have to actually tell it to use the InstanceID? It just magically knows?

When do these ID's and Tokens expire? Do they expire? I store the Token as a string on the server, but if at any point one of these expires, how do I know they have expired? I can always generate a new InstanceID and Token, that much seems easy, but then do the old ones stay active? How do I wipe the old tokens from the server? There seems to be an easy way to do this with APNS on the iOS side of things, where you can retrieve a list of all the expired tokens and just wipe them from your database.

3

There are 3 answers

7
pumpkinpie65 On BEST ANSWER

I've found myself asking most of these questions myself as I update my GCM implementation. After messing around with it a few days, here's my take on your questions.

From what I understand (and please correct me if I'm wrong), my server has an API Key and a Sender ID. Using the Sender ID I can have my client request a Token via the InstanceID stored locally on my client.

This is correct.

The InstanceID is assigned the moment my app goes online?

It looks like it's assigned as soon as your app launches, even if the device can't access the Internet.

Does it ever change? What about when the app upgrades or is uninstalled and reinstalled (or the device is restored)? By calling InstanceID.getInstance will I always retrieve the same InstanceID, or will it eventually expire and give me a new one?

According to the InstanceID documentation:

Instance ID is stable but may become invalid, if:

  • App deletes Instance ID
  • Device is factory reset
  • User uninstalls the app
  • User clears app data

If Instance ID has become invalid, the app can call getId() to request a new Instance ID.

I've tested uninstalling the app and clearing the data, and the results point to all of the above being true.

Is there any value to storing the string you retrieve by calling getID()?

It looks like the API handles storing this in your app's local storage for you.

Using the InstanceID, my client can request a Token from the GCM servers, which it then sends to my app server. My app server stores this Token, and can use this to send messages to the GCM servers, which will then send the message to the device. The device uses the stored InstanceID to actually receive these messages, I believe. So having a class that extends GcmListenerService will allow me to receive these messages with onMessageReceived? I don't have to do anything special (other than defining it in the AndroidManifest)? I don't have to actually tell it to use the InstanceID? It just magically knows?

As far as I can tell there wasn't any sort of InstanceId in the previous implementation, and it doesn't look like it's being explicitly used in this one either. If it is, it's being called within either GcmReceiver or GcmListenerService.

When do these ID's and Tokens expire? Do they expire?

I've already addressed ID's expiring and we can find out about Tokens expiring in the Android InstanceID implementation guide:

The Instance ID service initiates callbacks periodically (for example, every 6 months), requesting that your app refreshes its tokens. It may also initiate callbacks when:

  • There are security issues; for example, SSL or platform issues.
  • Device information is no longer valid; for example, backup and restore.
  • The Instance ID service is otherwise affected.

The guide says to subclass InstanceIDListenerService and override onTokenRefresh() to handle these scenarios.

I store the Token as a string on the server, but if at any point one of these expires, how do I know they have expired?

The guide for implementing GCM on your server says that the GCM server will respond to your server with some information about the token you used to try to send the push notification.

I can always generate a new InstanceID and Token, that much seems easy, but then do the old ones stay active?

My tests suggest that yes, they do.

How do I wipe the old tokens from the server? There seems to be an easy way to do this with APNS on the iOS side of things, where you can retrieve a list of all the expired tokens and just wipe them from your database.

I'm still looking into this and will update if I can figure something out.

0
Darush On

What is Instance ID?

Instance ID provides a unique ID per instance of your apps. You can implement Instance ID for Android and iOS apps as well as Chrome apps/extensions.

In addition to providing unique IDs for authentication, Instance ID can generate security tokens for use with other services.

Key Features

  • Generate Security Tokens
  • Verify app authenticity
  • Confirm app device is active
  • Identify and track apps

Instance ID lifecycle

  1. The Instance ID service issues an InstanceID when your app comes online. The InstanceID is backed by a public/private key pair with the private key stored on the local device and the public key registered with the Instance ID service.
  2. Your app can request a fresh InstanceID whenever needed using the getID() method. Your app can store it on your server if you have one that supports your app.
  3. Your app can request tokens from the Instance ID service as needed using the getToken() method, and like InstanceID, your app can also store tokens on your own server. All tokens issued to your app belong to the app's InstanceID.
  4. Tokens are unique and secure, but your app or the Instance ID service may need to refresh tokens in the event of a security issue or when a user uninstalls and reinstalls your app during device restoration. Your app must implement a listener to respond to token refresh requests from the Instance ID service.

When does Instance ID become invalid?

  • App deletes Instance ID
  • Device is factory reset
  • User uninstalls the app
  • User clears app data

If Instance ID has become invalid, the app can call getId() to request a new Instance ID. To prove ownership of Instance ID and to allow servers to access data or services associated with the app, call getToken(String, String).

When to refresh tokens?

The Instance ID service initiates callbacks periodically (for example, every 6 months), requesting that your app refreshes its tokens. It may also initiate callbacks when:

There are security issues; for example, SSL or platform issues. Device information is no longer valid; for example, backup and restore. The Instance ID service is otherwise affected.

All you need to know about Instance ID can be found in the following official links:

0
Ersoy On

Here is what I did to detect invalid tokens in my database.

There is a dry run option in GCM when sending a notification to user/list of users. When you set dry-run while sending notifications, it doesn't alert clients or show notifications to them but returns response about which tokens are valid(200) and which are not.

If you send a notification to 200 users with using dry-run option, then in the same order you will get the response from GCM.