Correct way of storing API Keys in flutter following best practises
Which is the correct way(best practice) of adding secret API keys in flutter in case I want to push the code on github. I've made a simple app that consumes an API but I used the key in a crud way just to test whether the app is working. Usually from my experience developing applications in the back-end, Keys are stored somewhere and in different file then one would simply import it to the required file that needs the API_KEY
and exclude the file in .gitignore
file.
So far I have also implemented this approach:
Folder tree
-lib
-auth
-keys.dart
-secrets.json
secrets.json
This is where I will add the KEY
and specify this file in .gitignore
to be excluded from being added in github when I push my code.
//Add API KEY HERE
{
"api_key": "ee4444444a095fc613c5189b2"
}
keys.dart
import 'dart:async' show Future;
import 'dart:convert' show json;
import 'package:flutter/services.dart' show rootBundle;
class Secret {
final String apikey;
Secret({this.apikey=""});
factory Secret.fromJson(Map<String, dynamic>jsonMap){
return new Secret(apikey:jsonMap["api_key"]);
}
}
class SecretLoader {
final String secretPath;
SecretLoader({this.secretPath});
Future<Secret> load() {
return rootBundle.loadStructuredData<Secret>(this.secretPath,
(jsonStr) async {
final secret = Secret.fromJson(json.decode(jsonStr));
return secret;
});
}
}
I feel like this approach is too much. I would like to get suggestions of a better approach.
EDIT: Look at J. Saw's comment below.
EDIT 2: The issue in described at the bottom has been fixed in firebase-config 19.0.2
.
Use Inside the Firebase console, inside the menu, scroll down to Firebase Remote Config
.Grow
and then Remote Config
. Here you can add a parameter with a value. When you're done don't forget to publish the changes. It's kind of subtle.
Now install firebase_remote_config for Flutter.
After importing everything, you can retrieve your value using this code:
RemoteConfig remoteConfig = await RemoteConfig.instance;
await remoteConfig.fetch(expiration: Duration(hours: 1));
await remoteConfig.activateFetched();
remoteConfig.getValue('key').asString();
This way, the API key or token is never part of your application.
Note: there is currently an issue where you get a warning stating the application's name is not set, but this won't affect functionality.
For secure storage you have to rely on the corresponding native platforms, both iOs and Android provide a mechanism to securely store keys. You can implement it by yourself and use the flutter channels to obtain and store the keys. Information about this mechanism can be read here:
Android Keystore
iOs KeyChain
Also, you can use this flutter plugin, which uses the services mentioned above and provides a dart object to access the secure storage.