My key is restricted using package name and SHA1, still Google Play store shows this warning.
Any idea why it is showing like this. I defined my API key in build.gradle file and using it from there.
My key is restricted using package name and SHA1, still Google Play store shows this warning.
Any idea why it is showing like this. I defined my API key in build.gradle file and using it from there.
As per google's recommendation putting restrictions such as specifying the package name and also the SHA-1 key is the way to go.
It has been explained here: https://cloud.google.com/docs/authentication/api-keys#securing_an_api_key
Now, the problem here is that whatever you do your API key will end up in the codebase i.e if you specify it outside your codebase (via some properties file) but pass it in via the BuildConfig field during the build phase (the whole key is visible to someone decompiling your code as it is now part of BuildConfig class file) or you split it up and concatenate in the codebase (the split keys are still visible and anyone can concatenate them by seeing the usage to get the final key from a decompiled apk).
The split key version will get rid of the warning in the Play Console, but the key is still exposed.
My suggested solution thus would be to encode your API key and pass that around your codebase. Just before using it you decode it back.
A very simple example can be:
Please use a better encoding algo and not this, this is for demonstration purpose only. Here we are using Base64 encoding.
import android.util.Base64
fun main() {
// API Key = "123456ABC"
val myEncodedApiKey = "MTIzNDU2QUJD" // Should be passed via BuildConfig
val decodedApiKey = Base64.decode(myEncodedApiKey, Base64.DEFAULT)
// Now use `decodedApiKey` in your codebase.
val decodedApiKeyString = String(decodedApiKey)
}
Why is this better?
Update (clarification on using the google-services.json file for API key):
The solution to use the API key from google-services.json isn't quite valid. google-services.json is generated file usually if you connect your firebase account. The API key defined there has a different restriction model. The one you define in your GCP project is different, allowing you to pass in package name and an SHA-1 key as well as restricted to a specific kind of API access such as Youtube only access. So if one was to use the API keys from google-services.json then you are essentially not using the restrictions you set up in your GCP account. GCP accounts do not generate google-services.json file.
To bring into perspective here is an official doc from Google for setting up Youtube API which uses GCP project defined API keys and in the docs, it mentions to directly put the keys in the code. (which is anyways wrong as it is exposed, but that's Google for you).
https://developers.google.com/youtube/android/player/setup
Nowhere in any docs, it is referred to use google-services.json file for retrieving API keys.
Got Google Play Ads? It would appear that, at least as of 8-1-19, an api key that triggers this is embedded within the full google play services ads library. That is--
implementation 'com.google.android.gms:play-services-ads:18.1.1'
triggers the alert, but
implementation 'com.google.android.gms:play-services-ads-lite:18.1.1'
which removes some code that already exists in the play store, does not. The error itself cites an obfuscated method, which I tracked down in the apk to:
com/google/android/gms/internal/ads/[obfuscatedstring]/<clinit>()
This appears to set a bunch of constants. One of which is called gads:safe_browsing:api_key
Just in case I'm wrong and this isn't in everyone's code I won't reproduce it here, but it sure looks to me like a GCP key that might trigger the issue. It is 40 characters and this identical key can be found elsewhere on the Internet.
My guess is, if you're using the play-services-ads library (as opposed to the Firebase library), it is probably seeing this string and sounding an alarm.
You can remove this warning by split your keys into 4 parts like this
public static final String API_KEY_PART_1 = "Asdsdfdd-";
public static final String API_KEY_PART_2 = "dfsFdsdsFdd";
public static final String API_KEY_PART_3 = "Pgdhs_SfSfs";
public static final String API_KEY_PART_4 = "fdfDDSD";
and use it by concatenate Strings
.attest(nonce.getBytes(), Constants.API_KEY_PART_1+Constants.API_KEY_PART_2+Constants.API_KEY_PART_3+Constants.API_KEY_PART_4)
NOTE: Make sure you restrict your API key to Applications Access only. otherwise if someone decompile your apk and use your api key then it may be increase your billing.
Restric your API's Key with SHA & Package name click here for details
Sorry, a bit late to the game here...
Follow the below steps:
you could get the api key with:
activity.getResources().getString(R.string.google_api_key);
String key name is "google_api_key" for getting the API Key.
FYI, The google-services.json file gets parsed and its values get added to an xml (path: app/build/generated/res/google-services/{build_type}/values/values.xml) which you have access to: https://developers.google.com/android/guides/google-services-plugin
Sorry, a bit late as my previous answer was just bypass the warning after some research i found an appropriate fix for this problem
you can get api key from google json file. The google-services.json file gets parsed and its values get added to an xml which you have access to all the elements of json as Android resources in your Java code click here for details
Below is an example to access the google api key from json file :
activity.getResources().getString(R.string.google_api_key);
it may be late, but will help some of the guys,
There is no link between Firebase JSON configuration file and google maps integration API key
Firebase Clarification
If you integrate Firebase in your app, it requires the JSON configuration to be placed in your code, and this is the only way to connect the app with Firebase.
but in Google maps, it is totally different. It will provide the key - to place in our code but not hard-coded or as it is,
Solution:
I have combined both solutions to work around, from Nishant and Sahil Arora, to encode the key into something else and split it into pieces to make it somehow difficult to decode back, I am splitting into the four-part, you can as much as you feel good:
Decode your ApiKey
// getEncodedApiKey result encoded key,
// splitted into four the part
String thePartOne = "encodedPartOneMaybe";
String thePartTwo = "encodedPartNextMaybe";
String thePartThree = "encodedPartNextMaybe";
String thePartFour = "encodedPartLast";
public String getSplitedDecodedApiKey(){
return new String(
Base64.decode(
Base64.decode(
thePartOne +
thePartTwo +
thePartThree +
thePartFour ,
Base64.DEFAULT),
Base64.DEFAULT));
}
Encode your ApiKey
//just to encode the string before splitting it into the pieces
//and remove this method from the source code
public void getEncodedApiKey(){
String plainApiKey = "xiosdflsghdfkj"; //
String encodedApiKey = new String(
Base64.encode(
Base64.encode(plainApiKey.getBytes(),
Base64.DEFAULT),
Base64.DEFAULT));
Log.i(TAG, "getEncodedApiKey: " + encodedApiKey);
}
better to use firbase firestore database to store your api key and access it. Firestore is safe and highly secure as its a product of Google.
and access it using this code
mDatabase.collection(COLLECTION_NAME)
.document("DOCUMENT_NAME")
.get()
.addOnSuccessListener(new OnSuccessListener<DocumentSnapshot>() {
@Override
public void onSuccess(DocumentSnapshot documentSnapshot) {
Log.d(TAG, "google_places_api_key: " + documentSnapshot.get("google_places_api_key") + "");
}
});
This method is safe and secure and your api key will not access by any Man in the middle attack and of course play store will allow this method.
Had the same issue for a long time, in my case while initializing the Youtube Player with google api key.
It didn't go away even after restricting the API Key with SHA & Package name.
However, after migrating to androidX the Security alert is gone in Google Play Console.
This error comes when developers write the API keys exposed as hardcoded strings in Java or XML files. Use it inside a strings.xml. And reference it as mentioned below. It will get resolved automatically.
geoApiContext = new GeoApiContext.Builder()
.apiKey(getResources().getString(R.string.maps_api_key))
.build();