In my android application, I have utilized G+ logins to authenticate the user on the device, and I have implemented a basic GCM server to get a GCM registration ID for that device as well.
Once a device has both authenticated the user and received a GCM registration ID, I'd like it to let my server know that, for example, registration ID XYZ is associated with tim#gmail.com. This part I understand how to do. What I'm not sure of is how I can make sure that it's REALLY tim#gmail.com.
How can I be sure that the email/GCM registration ID pairs coming from devices is authentic?
Google allows you to verify back-end calls from your Android app by utilizing GoogleAuthUtil
to retrieve a string called an “ID Token”. You send the token to your back end and your back end can use it to quickly and cheaply verify which app sent it and who was using the app.
By passing the ID token with your registration ID call to the server, you can verify that the message is authentic and from your Android app.
Related
I have an application which is already built. Now I want to use FCM to send messages between server and users.
As I understand each device has its own token which I can use to send message, and this token can be retrieved from
FirebaseInstanceId.getInstance().getInstanceId()
Correct me If I am wrong.
The application and backed server works fine and bellow my workflow
1- User open the android app.
2- Android app take the user token ID for authentication and device token for
messageing and send them to the server.
3- The back end server verify the user via
decodedToken = FirebaseAuth.getInstance().verifyIdToken(login.getToken());
then it save the token for sending the message.
Sending message working fine until I stuck with the following scenario.
The application allows multiple devices to login with same user, which means for 1 USER can have multiple tokens for messaging.
In this case I want to send message to all devices logged in with this user.
So how I can do this without changing the current design of my application
You need to change your DB and add ability to save all device tokens from one user. Then you need to call this Firebase api https://fcm.googleapis.com/fcm/send as many times as the tokens user have. Here the official documentation.
https://firebase.google.com/docs/cloud-messaging/http-server-ref
To update device specific token when it is changed on client side, you also have to bound that token with the deviceID, so to have that you need to pass the DeviceId to the server when passing the Firebase token. As deviceID can serve Android unique deviceID, or the id that provides Firebase in client side FirebaseInstanceId.getInstance().id. And here how to get Android deviceID
Is there a unique Android device ID?
If you use access_token for login the user, as another alternative, you can bound firebase token with user access_token, as it is unique for any device the user logged in.
Is it possible to use GCM without any GCM related logic on the client side? The idea is that mobile app shouldn't store / renew tokens etc. Mobile app should just initialise session with the middleware backend which will return back the internal device id and that's it (backend server will register device in GCM / APNs).
The goal is to reduce client side logic and simplify integration, so the flow probably should look like: APP <-> BACKEND <-> GCM
I do not think you can, the documentation states "this app must register with GCM and get a unique identifier called a registration token". There is a whole song and dance the client has to do with GCM that a backend isn't allowed to do. Plus, if the GCM server doesn't know which device is which registration id, it wouldn't know what client to send a notification to.
To GCM documentation states only one process of registering a client:
The client app obtains a registration token using the Instance ID API. The call to this API must have the authorized entity set to your app server's sender ID, and the scope set to the appropriate value for GCM (depending on your platform). Refer to the API reference for full detail on this API.
The client app passes the registration token to the app server.
The app server saves the registration token and acknowledges to the client app that the process completed successfully.
I am developing an app which has login functionality.I am generating only one gcm registration ID per app. If other user sign's in in same app he will start receiving notifications intended for the previous user.
How to handle this situation, so that each user will get notification intended for his/her?
Should I generate gcm reg id for each user?
What is the standard way to handle this situation?
You could try the following things:
When the user logs off, send a request to delete the token on your server, and erase it on your app;
Once the user logs off, you could simply remove the association of "User ID" to "GCM Token" (Or Registration ID) on your server. And when someone logs in again, you make a new association to that Token.
The GCM Token is app specific, but the association you make on your server is totally up to you.
And I can't stress it enough, the token generated by GCM is APP SPECIFIC. If your user logs in on multiple devices, your server should handle that, associating the user ID to multiple Registration ID Tokens.
An ID issued by the GCM servers to the Android application that allows
it to receive messages. Once the Android application has the
registration ID, it sends it to the 3rd-party application server,
which uses it to identify each device that has registered to receive
messages for a given Android application. In other words, a
registration ID is tied to a particular Android application running on
a particular device.
And from the docs, your server should also:
Before you can write client apps that use GCM, you must have an
application server that meets the following criteria:
Able to communicate with your client.
Able to send properly formatted requests to the GCM connection server.
Able to handle requests and resend them using exponential back-off.
Able to store the API key and client registration tokens.
Able to generate message IDs to uniquely identify each message it sends. Message IDs should be unique per sender ID.
EDIT: You can read more about GCM here.
For further reading, you could also read more on Device Group Messaging.
You can also download some code samples here.
You should store regID as per user.
This is because there is test cases that user1 logs out and user2 logs in. In that case if you have stored regID app specific and not binding with user then user2 will also get notification.
So you need to store regID as per user , app and as well as device specific.
Of course yes every time someone downloads your app, your app should register them with the GCM and be given a reg token, this needs to be sent to your app server, on your app server you need to sort out who you are sending the notification too. you should probably send some login info and reg token when they login so you can identify each person, then write some php or Jquery to send to individual users or all. you should also send the reg token every time they login as these can change without warning.
Your app server should be able to handle removing unused reg tokens and adding new ones
Each android device generate a Unique GCM reg id. push notification from server side will send according to the device id. So at Login time you can send GCM reg id to your server. So from server side push notification will send to device.., that is actual functionality.
Hope this will help
I know there is unique registartionId get from users email address for sending message to his device, but also do i need to have different authenctication id for each user?
If I am right we just need registrationId to send message to user, where as AuthenticationId is static, which is use to send message to user with registration id.
but in my case, I got Authentication Token using my developer email address, and if send message to the same email address I receive message. and If I send message to another user using registration id received from his email address and using authentication token got from my developer account email address user didn't receive message.
and again if I use authentication token got from user's email address and password and using his registration id user receive message.
The authenticationToken confirms that you have a valid Google account and thus are in general allowed to send C2DM messages. The registrationToken is directly tied to a user's device and your application. It allows your application to use your authenticationToken to send a message to the user's device.
You need one authenticationToken to send messages to all devices for which you have registrationTokens. Note however, that you should pick up a new authenticationToken every time you start sending messages, as those can be changed by Google at random.
I recall reading that Google advises to use different mail accounts for sending and receiving.
To the best of my knowledge the Authentication token is generated against the c2dm gmail id and the gmail account configured on the device.
That may be the reason why the other user is not receiving messages using your registration id.
So the answer to your question is yes, you need to have different Authentication Token for different user for sending message using C2DM.
You're correct that the authentication token is static, it serves to authenticate the app to the C2DM service. The registration id serves to identify the user you are sending the message to.
Since you are using your developer email account, it might be that the authentication token is invalidated. Did you check that? You'd get a 401 error sending the message. You shouldn't be using or collecting authentication tokens from your users, that shouldn't even work.
Note that C2DM assumes you are using a server component for your app as described here: http://code.google.com/intl/nl/android/c2dm/index.html#arch.
If you are trying to send a message to the C2DM server from the device, you're doing it wrong.
I'm developing an application that uses C2DM to receive push notifications. I've implemented the whole C2DM circuit (both client and server) and it's working fine.
Currently my applicacion has a button to bootstrap the C2DM registration, when receiving the registration id token from Google I call a webservice in my app server to associate the device with the registration id.
I'm going to implement authentication in my application and I have a few question related to the handling of the C2DM registration.
The client application (ie the Android one) will have a login screen as the first screen so the user can enter the credentials. As soon as the credentials get validated I'm planning on calling the C2DM registration so the user gets associated with a registration id token. Is this ok? In later executions of the application I will probably store the credentials or some sort of token so the user doesn't need to enter the credentials again, Should I also fire the C2DM registration when the application launches?
I'm aware that Google may eventually update the registration id. Is it a good practice to also update the registration id on a regular basis? If so, when should be appropiate? Does the registration id token expire?
What happens in the rare case of a desynchronization of the registration id between the client and the server (eg a new registration id arrives at the client, in the middle of that a new event is fired on the server with the old registration id, then the registration id arrives at the server)? Will Google handle this cases? Should my app server handle this cases?
What happens if the server is not reachable when a new registration id arrives from Google? Should I backoff and schedule an Alarm to try again?
Can you think of any other pitfalls with this?
1) I would fire the C2DM registration as soon as possible. Nothing in particular, but since the request is asynchronous, firing it up early will help me get the reg ID sooner. However, no need to fire the registration each time the app starts. Once is sufficient.
2) Whenever Google decides to update the reg ID it will send it to the device and you need to do the same steps you followed when you receive the reg id for the first time i.e. convey it to the server.
3 & 4) You may want to go through this documentation. It stresses the fact that you need to make it sure that you send the registration ID to your server and keep on trying. I assume here that if the reg ID is refreshed, and your server still has the old ID, it will not be able to send messages to the device. It will receive a 200OK with an Error Code of InvalidRegistration which means a (missing or) bad registration id.
5) Cannot comment much - would say that it depends on the design of your application. But one thing worth noting is that C2DM is still in Beta so expect things to be different in the long run.
Try to prompt the user with a choice of google accounts that are already on the phone. The http://code.google.com/p/chrometophone/source/checkout shows this. Look at SetupActivity.java for getGoogleAccounts(), etc.