Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a safe way to manage API keys?

I am using an API within my app. I currently manage the API key from a java interface

public interface APIContract {     //The API KEY MUST NOT BE PUBLISH. It is possible to generate a new one for free from www.themoviedb.org     //Remove before commit !!!     String API_KEY = "abcdefghijklmnopqrstuvwxyz";     /... } 

This do the job. I can access the key using APIContract.API_KEY, but as you can see in the comment this is not safe if I use git and a public repository (I am not suppose to publish this key).

So here is my question : is it possible to move this key in another place which I can easily access from my app but which will not be committed ?

I found this thread which use gradle to store the key, but I need to commit the build.gradle file so it does not do the job.

Does someone know how to solve this problem ? I did not find similar problem in stackoverflow but maybe I missed something

EDIT I love the idea of moving the key outside any java code because other people (maybe non technical people) can easily manage their own key. I was thinking about using a gradle file like settings.gradle.

like image 550
ThomasThiebaud Avatar asked Oct 14 '15 19:10

ThomasThiebaud


People also ask

Is it safe to give someone your API key?

API keys are generally not considered secure; they are typically accessible to clients, making it easy for someone to steal an API key. Once the key is stolen, it has no expiration, so it may be used indefinitely, unless the project owner revokes or regenerates the key.

What is the best place to store secret API keys?

Often your app will have secret credentials or API keys that you need to have in your app to function but you'd rather not have easily extracted from your app. If you are using dynamically generated secrets, the most effective way to store this information is to use the Android Keystore API.

Which is the most secure method to transmit an API key?

HMAC Authentication is common for securing public APIs whereas Digital Signature is suitable for server-to-server two way communication. OAuth on the other hand is useful when you need to restrict parts of your API to authenticated users only.


2 Answers

1. Store api keys in an xml file

Put xml file "api_keys.xml" in the directory "res/values/".

api_keys.xml

<?xml version="1.0" encoding="utf-8"?> <resources>     <string name="THE_MOVIE_DB_API_TOKEN">XXXXX</string> </resources> 

use api keys in java code

context.getString(R.string.THE_MOVIE_DB_API_TOKEN); 

2. Store API keys with help of Gradle and the gradle.properties file

Example_0 Example_1

Add the following line to [USER_HOME]/.gradle/gradle.properties

For Windows OS, an example for Denis user:

C:\Users\Denis\.gradle 

gradle.properties

MyTheMovieDBApiToken="XXXXX" 

Add the following code to the build.gradle file

build.gradle

apply plugin: 'com.android.application'  android {     ...      defaultConfig {         ...     }     buildTypes {         release {             ...         }     }     buildTypes.each {       it.buildConfigField 'String', 'THE_MOVIE_DB_API_TOKEN', MyTheMovieDBApiToken     } } 

use api keys in java code

BuildConfig.THE_MOVIE_DB_API_TOKEN) 

3. Store API keys with help of gradle and the system path variable

Example_0

Add new system PATH variable THE_MOVIE_DB_API_TOKEN="XXXXX":

For Windows OS:

  • open system
  • advanced system settings
  • environment variables
  • add new variables to the user variables

Add the following code to the build.gradle file

build.gradle

apply plugin: 'com.android.application'  android {     ...      defaultConfig {         ...     }     buildTypes {         release {             ...         }         buildTypes.each {             it.buildConfigField 'String', 'THE_MOVIE_DB_API_TOKEN', "\"$System.env.THE_MOVIE_DB_API_TOKEN\""         }     } } 

use API keys in java code

BuildConfig.THE_MOVIE_DB_API_TOKEN 

Link to my gist on github

like image 87
Denis Avatar answered Sep 20 '22 18:09

Denis


Here is another way:

Place the API key in a file accessible to the build machine/server, we'll call it:

/usr/api_user/api_key1 

With contents:

myApiKey = abcdefghijklmnopqrstuvwxyz 

You will now access it using the `BuildConfig' gradle object. Modify your code to this:

public interface APIContract {     //The API KEY MUST NOT BE PUBLISH. It is possible to generate a new one for free from www.themoviedb.org     //Remove before commit !!!     String API_KEY = BuildConfig.MY_API_KEY;     /... } 

Then in your build.gradle, add something like this:

buildConfigField "String", "MY_API_KEY", getMyApiKey("myApiKey") 

And also add this:

//return a MY API KEY from a properties file. def getMyApiKey(String property){     Properties properties = new Properties()     properties.load(new FileInputStream("/usr/api_user/api_key1"))     return "\"" + properties.getProperty(property) +"\"" } 

You can relocate the API directory location, as you can tell, so that it is not a part of your repo. Of course, then it will have file system dependencies for the build... which you could have a list setup in a CI/CD environment (maybe a tool like Jenkins) to replicate the build files to a private repo, for backup purposes.

like image 43
Jim Avatar answered Sep 21 '22 18:09

Jim