Why is api_key/current_key updated in google-services.json - android

It has been a while since we touch this google-services.json file. We download the file again from Firebase console and do a diff for it with whatever we have on file and saw that the api key is different 🤔.
However, we could not find any good documentation about why it is changed and what is supposed to do on our side.
"api_key": [
{
- "current_key": "AI***********************************BC"
+ "current_key": "AI***********************************K0"
}
],
We saw this question that this api key is supposed to be used to send push notifications. We tested notification with both versions of the key and both of them are working fine.
https://stackoverflow.com/a/38227768/1035008
What might be causing the change in the current_key field in the JSON file? Is it safe to just swap in the new file?
Edit:
We saw the old key is still there under https://console.firebase.google.com > Project Overview > Project Settings > Web API Key:
I guess Google just decided to move the web API key outside of file and created a new one for each project?

A Firebase project can have many API keys, but each API key can only be associated with a single Firebase project. See The docs
You can view your API keys in Firebase console at APIs & Services > Credentials
From what I can gather, when you download the google-services.json it 'auto matches' what it thinks is the most appropriate key. In my case it changed the key to a different (existing) key, but both keys still work - tested with FCM Push Notifications and Firebase Analytics on Android device.

Related

FCM Notification is not working If i send it by using ARC ( Advanced REST API )

I integrated the push notification system with Firebase in my project and it's working well except one thing.
If I try to send a notification from Firebase console, using Device Token & Topic, the notification shows in device.
If I try to send a notification from ARC ( Advance REST CLIENT) using Device Token, the notification shows in device.
If I try to send a notification from ARC ( Advance REST CLIENT) using my topic, NOTHING HAPPENS.
Requested URL : https://fcm.googleapis.com/fcm/send
RAW headers :
Content-Type: application/json
Authorization: key=AIz.....
RAW PAYLOAD :
{
"data":
{
"employeename":"kumaran","empid":"234444"
},
"to":"/topics/bmmembers"
}
Response Header
Status : 200: OK
JSON :
{
"message_id": 6536474446058224000
}
But my device not received any notification and checked Logcat whether any json arrived in client end, but not received.
Any idea and how we need to resolve this issues.
This is my trial and error type of a "Solution found for this Issue":-
Issue found is "The Quota for the particular Server-key or credential or the whole Google API Account itself might have been expired or used the limit. "
Below i have explained how i once again successfully received FCM Notifiaction with Image for the same Android App.
ISSUE:-
I was unable to send FCM push notification (with image) from Advanced REST Client, by using the Android key generated from Google API console in my very old created Project (Eg: My Project; that has 5-apps and its credentials).
I tried sending the Post request from ARC client many time but dint receive any single FCM notification in my Android Mobile.
SOLUTION I FOUND WAS:-
1a. I deleted the credentials (API key, server key,web key, OAuth key etc) in Google API console related to that particular app (Eg: FCM App1).
1b. Also i went to Firebase console and deleted the particular app in its project also.
Finally now the App (Eg.FCM App1) doesn't contain connection with
1.Google API console and with
2.Firebase Console.
1c. I also deleted the "google-services.json" file from the Android studio->Project folder.(If you are unable to delete this, try executing File->'Invalidate cache and restart' option and then retry deleting it. It will get deleted.)
Next, freshly
I created a new gmail account, and opened a new Google API Account, further opened a fresh new Project in that Google API Account (Eg: My Project1).
Next, I went to Firebase console signing in with this newly created Gmail acccount, opened a fresh new Project, selected "Add App" and selected "Android".
-> entered my package name, SHA1 key and Added the App.
-> Also downloadedthe new google-services.json file and added again in the Project folder in Android Studio.
-> And followed everything as per previous procedure.
==> Finally I got the fresh ""Server-Key"" in the new Google API console. Copied this server-key and pasted in Advanced REST client at place Authorization:key=AIzaSyAJzs-DDD......etc.
=> added the correct TokenID freshly created for this App from Log.
===> Pressed SEND button in the ARC, and WOOOOWWWW....
within few seconds I GOT THE FCM NOTIFICATION WITH IMAGE IN MY ANDROID MOBILE EVENTHOUGH MY APP WAS IN BACKGROUND OR COMPLETELY CLOSED at that time....!!!

Firebase invites says invitation sent but has not been received

I've trying to send invitations with Firebase Invites. When select an email from a contact, Firebase says that has sent the invitation, but the email is never received.
On the console the SHA1 certicates are configurated.
The errorcode returned is always RESULT_OK and the number of invitations returned from AppInviteInvitation.getInvitationIds is correct.
The SDK is updated on gradle with the latest version, 10.0.1, like explained on the documentation.
The code that creates the invitation is:
Intent intent = new AppInviteInvitation.IntentBuilder(title)
.setMessage(msg)
.setCallToActionText(callToActionText)
.setOtherPlatformsTargetApplication(AppInviteInvitation.IntentBuilder.PlatformMode.PROJECT_PLATFORM_IOS, IOS_CLIENT_ID)
.build();
Any ideas?
I had the same problem and I managed to fix it, although I am not pretty sure what step actually helped.
It's worth specifying that in my case the email was perfectly sent when I removed the method call:
.setOtherPlatformsTargetApplication(...)
The following steps were applied:
All fields were filled on Firebase console for Android and iOS project settings (including App ID Prefix and App Store ID).
SHA-256 hashes (from debug and release keystore) were added for Firebase Android project settings:
keytool -exportcert -keystore path-to-debug-or-production-keystore -list -v
Updated google-services.json was downloaded from Firebase Android project settings and added to the application root (with GoogleServicesJson Build Action for Xamarin). So the file among others contains the following:
...
"appinvite_service": {
"status": 2,
"other_platform_oauth_client": [
{
"client_id": "1234567890-specified_ios_client_id.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "ios.app.bundle.id",
"app_store_id": "9876543210"
}
},
...
]
}
...
The specified client_id is the same in .setOtherPlatformsTargetApplication(...) method call and in google-services.json
Also Firebase Invites had been previously adjusted for the iOS project, but I don't see if it could help for the Android anyhow.
Removing .setOtherPlatformsTargetApplication(...) allowed Android to send invitations again.
When invitations are received on iOS though, they work correctly opening link with:
Gmail or Mail with app installed (opens app correctly)
They do not work properly:
Link reading email in Safari with app not installed, goes to google
play store
Link in Gmail or Mail app, with app not installed, goes to google play store

How to programmatically access the Google API key in google-services.json

The app uses Google Cloud Messaging and contains a google-services.json file which itself contains Google API authentication info, including the API key. GCM functions as expected.
The app contains a testing facility that sends a GCM message using HTTP, and it needs the API key. How do I access that key, the one stored in google-services.json? I do not want to use GoogleCloudMessaging to send the messages (I'm using OkHttp and it does the job nicely).
Hopefully it is not necessary to duplicate it in the app.
Sorry, a bit late to the game here...
The google-services.json file gets parsed and its values get added to an xml which you have access to:
https://developers.google.com/android/guides/google-services-plugin
In your case, you could get the api key with:
activity.getResources().getString(R.string.google_api_key);
You can just get the API key off your GoogleCloud platform then go to credentials and you can grab your API key off of there.
https://console.developers.google.com/
Is that what your looking for?
But if you need to access it (which is should never change unless your change the json file itself) Then you could just parse the json file with a parser. But thats adding more work than needed. I would just copy and paste it from the web.
Ok I see what you going for try using this and using the NSDefualts
Store the token like this:
if (registrationToken != nil) {
self.registrationToken = registrationToken
print("Registration Token: \(registrationToken)")
//store the registation token for use in the postData function in the login page
self.loginInformation.setObject(self.registrationToken, forKey: "GCMToken")
let userInfo = ["registrationToken": registrationToken]
And retrieve it anywhere in the project like this:
myNoteGCMID = loginInformation.objectForKey("GCMToken") as! String
Then if it changes you don't have to change it in but just one place. The change will occur everywhere you call it.

How do I restrict Google App Engine Endpoints API access to only my Android applications?

I am an Android developer building my first Google App Engine (java) back-end for my apps. I don't want anybody else to access this API other than my app. (I plan to use App engine for verifying InApp purchases in my Android app). My data is not relevant to users so,
I don't want users to be able to access my API even if they are logged in with their Google accounts (on web or Android devices).
I followed the steps mentioned in - "Specifying authorized clients in the API backend"
(https://developers.google.com/appengine/docs/java/endpoints/auth)
like generating client IDs and add them in #Api (clientIds and audiences)
except "Add a User parameter" - since I don't need user authentication.
Then I deployed App engine and I am still able to access the API through API explorer (https://your_app_id.appspot.com/_ah/api/explorer)
(I haven't added API_EXPLORER client ID)
I tested with the APK that was built with the endpoint libs before adding client IDs and can still access the API.
Is adding a "User parameter" to all endpoint APIs a must? to achieve my purpose (restrict API to only my Android apps).
Can I pass null as userAccount name from Android client and ignore user parameter value on server (since it will be null)? Will this ensure that the API is accessible only from my android apps (since the client ID is generated for my package name and SHA1 of the APK?)
Should I use something like a service account for this purpose?
The documentation says for Android, both Android and Web client IDs must be added and audience must be the same as web client ID. Does this open access to any other web client? can I skip mentioning web client ID and still achieve my purpose?
Appreciate your time and help.
...... updating with my further investigation ...
I did the following:
Added User parameter to APIs on backend - but did not check for null value. API can still be accessed without passing any credentials (from Android debug APK and API explorer)
Then, I tried
mCredential = GoogleAccountCredential.usingAudience(this, "server:client_id:" + WEB_CLIENT_ID);
mCredential.setSelectedAccountName(null);
and passed this credential to API builder (as suggested in some other posts)
Caused FATAL EXCEPTION. So, we can't pass null account name.
I could call the API using API explorer without OAuth. But when I enabled OAuth, it gave error saying this client ID is not allowed! ( I haven't yet added com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID in client_ids{})
Then I added code to throw OAuthRequestException on the backend if the user is null. This resulted in API explorer getting errors without OAuth. It works with OAuth enabled after adding API_EXPLORER_CLIENT_ID to client_ids)
Added code to pass valid user account name(email) from my Android app. Then, I am able to access API only with my release APK. Even the debug APK gets exceptions! - which is what I expected..So, I assume no other Android apps will be able to access this API.
So, not checking for null user on back-end API is a bad idea (as suggested in other posts). It is as good as not mentioning any client_ids and not having User param.
Only question I have at this moment is: If some one can figure out the WEB_CLIENT_ID from the APK, will they be able to use it to build a web client to access my API (I haven't mentioned client secret anywhere in the code. So I am thinking this is not possible).
I did search Google groups and Stackoverflow, but still it is not clear.
(Authenticate my “app” to Google cloud endpoints not a “user”)
Authenticate my "app" to Google Cloud Endpoints not a "user"
(How do I protect my API that was built using Google Cloud Endpoints?)
How do I protect my API that was built using Google Cloud Endpoints?
(Restrict access to google cloud endpoints to Android app)
Restrict access to google cloud endpoints to Android app
I had a similar issue, not between Android and App Engine, but between a separate server and App Engine. The way I handled it was to add a signature hash field as a parameter to each API call. If the request had an improper signature, it would be denied.
For example, suppose your API end-point is example.com/api/do_thing?param1=foo. I would hash the entire url, along with a secret key, and then append the result of the hash to the request: example.com/api/do_thing?param1=foo&hash=[some long hex value].
Then, on the server side, I would first remove the hash from the url request, then run the hash on everything that was remaining. Finally, you check whether the calculated hash matches the one that was sent with the request and if they don't, you can deny the request.
It is very important however that your secret key remain secret. You have to be careful with this on Android because someone could attempt to decompile your APK.
Facing the same problem than you ! Authenticate Android End point without Google User Account is just impossible !
So here is my way to resolv this problem, without any user interaction (Maybe not the right but that works, and you've got strong authentication (SHA1 + Google Account)):
HERE IS MY ANDROID CODE
Get and Build Valid Credential
//Get all accounts from my Android Phone
String validGoogleAccount = null;
Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
Account[] accounts = AccountManager.get(context).getAccounts();
for (Account account : accounts) {
if (emailPattern.matcher(account.name).matches()) {
//Just store mail if countain gmail.com
if (account.name.toString().contains("gmail.com")&&account.type.toString().contains("com.google")){
validGoogleAccount=account.name.toString();
}
}
}
//Build Credential with valid google account
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience(this,"server:client_id:301991144702-5qkqclsogd0b4fnkhrja7hppshrvp4kh.apps.googleusercontent.com");
credential.setSelectedAccountName(validGoogleAccount);
Use this credential for secure calls
Campagneendpoint.Builder endpointBuilder = new Campagneendpoint.Builder(AndroidHttp.newCompatibleTransport(), new JacksonFactory(), credential);
HERE IS MY API BACKEND CODE:
API Annotation
#Api(
scopes=CONSTANTES.EMAIL_SCOPE,
clientIds = {CONSTANTES.ANDROID_CLIENT_ID,
CONSTANTES.WEB_CLIENT_ID,
com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID},
audiences = {CONSTANTES.ANDROID_AUDIENCE},
name = "campagneendpoint",
version = "v1"
)
Method code:
public Collection<Campagne> getCampagnes(#Named("NumPortable")String NumPortable, User user) throws UnauthorizedException {
if (user == null) throw new UnauthorizedException("User is Not Valid");
return CampagneCRUD.getInstance().findCampagne(NumPortable);
}
For the moment, it only works on Android (I don't know how we gonna do on IOS..)..
Hope It will help you !
Google provides ways to do this for Android, web and iOS
The steps involves:
Specifying a client Id for apps you want to allow to make requests to your API
Adding a User parameter to all exposed methods to be protected by authorization.
Generating the client library again for any Android clients
Redeploying your backend API.
Updating the regenerated jar file to your Android project for your Android client.
These steps are laid out in clear detail on Google's Using Auth with Endpoints and also on this blog
Facing the same problem, here are the result of my research :
Added Android cliend id with SHA1 fingerprint in Google console
Use of it in the API annotation
BUT :
If i dont add user parameter to methods : the check about android app client id does not work
If I add the USER parameter but do not ask the user to choose its google account to create the credential ... also it does not work ...
Conclusion : It seems to be mandatory to connect a user account for the check about the app client id to be executed ... I really do not understand why because no link exist between the 2 processes
Access this site
Choose your project, go to credentials section
Create a new api key
Create a new android key
Click on "Edit allowed android applications" and enter your SHA1 key; your android package name
Let me know if this solves the issues.

Why do I get "MismatchSenderId" from GCM server side?

I'm trying to create a push service for my Android app, and I follow Google GCM's documentation and example for this matter:
I can register/unregister my Android app. From my server side, I can see that I have one subscription registered, but when I try to send a message from server to my Android app I always get following error:
Error sending message to device #0: MismatchSenderId
For my Android app, I use SENDER_ID = 200000000001.
And for my server side as Google says I use API_KEY = AIzxxxxxxxxxxxxxxxxXxxXxxXxxxXXXXXxxxxs
I followed this document:
http://developer.android.com/guide/google/gcm/demo.html
I've enabled GCM in my Google API panel too, yet I'll get that annoying error message.
How can I fix this problem?
Did your server use the new registration ID returned by the GCM server to your app? I had this problem, if trying to send a message to registration IDs that are given out by the old C2DM server.
And also double check the Sender ID and API_KEY, they must match or else you will get that MismatchSenderId error. In the Google API Console, look at the URL of your project:
https://code.google.com/apis/console/#project:xxxxxxxxxxx
The xxxxxxxxx is the project ID, which is the sender ID.
And make sure the API Key belongs to 'Key for server apps (with IP locking)'
Mismatch happens when you don't use the numeric ID. Project ID IS NOT SENDER ID!! It took me 9 hours to figure this out. For all the confusion created by google, check the following link to get numeric id.
https://console.cloud.google.com
instead of
https://console.developers.google.com
Hope it helps!!
Update:-
Things have changed again. Now the sender id is with firebase.
Go to https://console.firebase.google.com and select your project. Under settings -> cloud messaging, you can find the sender id.
And it works!
Please run below script in your terminal
curl -X POST \
-H "Authorization: key= write here api_key" \
-H "Content-Type: application/json" \
-d '{
"registration_ids": [
"write here reg_id generated by gcm"
],
"data": {
"message": "Manual push notification from Rajkumar"
},
"priority": "high"
}' \
https://android.googleapis.com/gcm/send
it will give the message if it is succeeded or failed
I encountered the same issue recently and I tried different values for "gcm_sender_id" based on the project ID. However, the "gcm_sender_id" value must be set to the "Project Number".
You can find this value under: Menu > IAM & Admin > Settings.
See screenshot: GCM Project Number
This happens when the Server key and Sender ID parameters HTTP request do not match each other. Basically both server ID and Server key must belong to the same firebase project. Please refer to the below image. In case of mixing these parameters from deferent Firebase projects will cause error MismatchSenderId
InstanceID.getInstance(getApplicationContext()).getToken(authorizedEntity,scope)
authorizedEntity is the project number of the server
Your android app needs to correct 12-digit number id (aka GCM Project Number). If this 12-digit number is incorrect, then you will also get this error.
This 12-digit number is found in your Google Play Console under your specific app, 'Service & API' -> 'LINKED SENDER IDS'
Check google-services.json file in app folder of your Android project. Generate a new one from Firebase console if you are unsure. I got this error in two cases.
I used a test Firebase project with test application (that contained right google-services.json file). Then I tried to send push notification to another application and got this error ('"error": "MismatchSenderId"'). I understood that the second application was bound to another Firebase project with different google-services.json. Because server keys are different, the request should be rewritten.
I changed google-services.json in the application, because I wanted to replace test Firebase project with an actual. I generated right google-services.json file, changed request, but kept receiving this error. On the next day it fixed itself. I suspect Firebase doesn't update synchronously.
To get a server key for the request, open https://console.firebase.google.com and select an appropriate project.
Then paste it in the request.
With the deprecation of GCM and removal of its APIs, it appears that you could see MismatchSenderId if you try to use GCM after May 29, 2019. See the Google GCM and FCM FAQ for more details.
Use sender ID & API Key generated here: http://developers.google.com instead (browse for Google Cloud Messaging first and follow the instruction).
If use for native Android, check your AndroidMaifest.xml file:
<meta-data
android:name="onesignal_google_project_number"
android:value="str:1234567890" />
<!-- its is correct. -->
instead
<meta-data
android:name="onesignal_google_project_number"
android:value="#string/google_project_number" />
Hope it helps!!

Categories

Resources