Android Question GCM Exposed Key

Marcos Alves

Well-Known Member
Licensed User
Longtime User
Hello all,

recently I received an alert in Google Play Console panel for one of my B4A apps about the exposing of a GCM key . This app uses GCM/Firebase Lib and it's code is written according the recommendations given by @Erel in that library tutorial. (this: https://www.b4x.com/android/forum/t...s-firebase-cloud-messaging-fcm.67716/#content)
I really wasn't secure about that piece of code when we write the Key = xxxx to use Firebase GCM library...
Then, is there any programming best practice to avoid this exposing risk? What is the recommendation? I was thinking to put the key in a server database and then recover it using a POST and store in an internal and encrypted sqlite database but ... is this the best shortcut to assure the security in this question or is there any easier and maybe better option?
 

DonManfred

Expert
Licensed User
Longtime User
Last edited:
Upvote 0

Marcos Alves

Well-Known Member
Licensed User
Longtime User
That's incorrect. You don't need to put the key in your app. It is only needed in the B4J program that sends the messages.
Ok @Erel , but that's not what is done in this code:
B4X:
   Job.PostString("https://fcm.googleapis.com/fcm/send", jg.ToString)
   Job.GetRequest.SetContentType("application/json;charset=UTF-8")
   Job.GetRequest.SetHeader("Authorization", "key=" & API_KEY)

Look... API_KEY is defined in the global Android process... This code is used in THIS tutorial ...
About sending FCN messages only from server, there are some situations when could be more interesting do not use the server but only to send the request to Firebase... example: when one of my app users sends a message to other... In the first message, my server receives a command and sends a FCN message to the target to "wake up" the app... later, the source could send a FCN message directly to the target if the previous message isn't still consumed in order to retry to wake up the target peer. This second FCN message doesn't require to be sent thru my server because the data payload is already there, waiting to be consumed. This is only a "wakeup" message with no data. To avoid to pass it thru my server saves CPU and network bandwidth...
 
Upvote 0

Marcos Alves

Well-Known Member
Licensed User
Longtime User
Add restrictions to your API key so that only your apps are allowed to use the API key. More details on adding restrictions to API keys can be found here.

Solution: Add a restriction to your Key. For ex. add your packagename and signhash: only your app can use the key then.[/QUOTE]

Thanks @DonManfred ... I really already studied about to restrict the API KEYS. but I must to confess that I'm a little afraid to do this because we already have more than 1000 users and I'm not sure what will be the behavior of the entire environment if I apply restrictions. For example, I use the same key to send messages from server and apps...
Maybe to download and store the key when app starts could be a good workaround no? At least I'll reduce the risk.
 
Upvote 0

Marcos Alves

Well-Known Member
Licensed User
Longtime User
I don't recommend putting the API key in the client apps. I will add a message about it in the tutorial to make sure that it is clear.
Ok @Erel ... So I think that to use the Android FCN library could be a good practice to recover the key from my own server, using a POST request with username and password provided by the users no?
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
Ok @Erel ... So I think that to use the Android FCN library could be a good practice to recover the key from my own server, using a POST request with username and password provided by the users no?
Maybe to download and store the key when app starts could be a good workaround no?
I would store the api key only if the phone has it's security set up (user has to unlock phone to use). Hints for testing this:
https://www.b4x.com/android/forum/t...tion-iskeyguardlocked-with-sony-xperia.34609/
https://stackoverflow.com/a/54413332
https://developer.android.com/reference/android/app/KeyguardManager.html
If the phone is not secured, I would always make the user download the API key and store it in memory only (maybe expire it now end then for additional security).
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
I would not store the FCM Admin key in a app at all!

I would use (i am using this):
- Store the Key on my server,
- I use a b4j server app which has access to the Key.
- I use okhttputils2 to to send a command to my server appp to send a Pushnotification to client X, the server send the Notification then.
 
Upvote 0

Marcos Alves

Well-Known Member
Licensed User
Longtime User
I would not store the FCM Admin key in a app at all!

I would use (i am using this):
- Store the Key on my server,
- I use a b4j server app which has access to the Key.
- I use okhttputils2 to to send a command to my server appp to send a Pushnotification to client X, the server send the Notification then.
Ok... but I'm talking about a server with more than 5000 messages/second and if I can reduce, let's say, in 10% the traffic I'll increase its capacity to manage clients with the same level of resources. So, if you can sometimes use only Firebase, you should do it agree?
The solution: request the key when needed using a POST method (and eventually stores it in an encrypted database in app). The vulnerability: developer console will not show the alert message anymore BUT an advanced attack could analyse the code and use the POST method to recover the key (but this requires a lot more of work in reverse engineering).
The definitive and secure solution: to restrict the key in Firebase panel... I think that's it right? :)
 
Upvote 0

Marcos Alves

Well-Known Member
Licensed User
Longtime User
Are there really 5000 clients connecting every second? This is about 18 million messages per hour.
Yes... I'm calculating and projecting the system resources and database to support at least 100K users and one single message has at least five control and status messages in background ... see:

- Standard Custom message:
- When an user sends a message to a target (not group):
- 1. The source app calls the send message method in server...
- The server stores the payload (data) and sends a FCN to target (with no Payload), title NewMessage
- 2. The target app wakes Up, verifies the FCN message title and, if required(*), requests the message queue from server
(*Depending on the title of FCN, could be only a signal message - system control or operational)
- The server stores a Received Type message on the source queue and sends a fcn message to the source to alert that the target received and downloaded the message

- 3. The target opens the app (if not open yet). A POST "opened" method is sent to the server ... the server checks the contacts list of target and sends a FCM message with the "on line" status to the members that are also on line... the on line status and start time is updated on server -
- Depending on the number of members of the target contacts list, maybe generate two of more FCN messages (typically 5-6)

4. The user opens the chat and reads the message
- The server stores the READ status in the source messages queue and send a FCN message to alert

This is almost the cycle of only one user message in our systems... there are also system control messages, alerts, broadcasts... a highly active user in our system uses about 35 FCN messages per minute. Today we have about 1.000 today (about 5% are highly active and each server of app cluster is sized to reach 100K total - 10k highly active).
It's easy to reach 100K FCN messages a day with only 200 or 300 active users. Then, when I can use a direct "link" from source to target it's recommended because will save a lot of system capacity (specially when involving status update or broadcast messages).
 
Last edited:
Upvote 0

Marcos Alves

Well-Known Member
Licensed User
Longtime User
18 Mio. messages IS a design mistake. What kind of messages do you send and why?
Hello @KMatle ... remember that FCN messages are used also to send system and control messages, not only user visible messages... see: a single user message has 4 status at least: waiting, received by server, received by target and read... the two last ones will require a FCN message from server to the source because maybe when the target receives and reads the source app couldn't be active anymore, and the message status in sqlite local database MUST to be updated to have a good app reliability... and the server MUST to be sized to support at least about 100K users... see the general process description that I posted to @Erel in my previous post...

regards!
 
Upvote 0
Top