Correct way of storing API Keys in flutter following best practises

DartFlutter

Dart Problem Overview


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.

Dart Solutions


Solution 1 - Dart

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 Firebase Remote Config. Inside the Firebase console, inside the menu, scroll down to 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.

enter image description here

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.

Solution 2 - Dart

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.

Solution 3 - Dart

As mentioned, if the key is a secrete and you would like to protect it then simply do not put it in the client app. The app can be de-compiled and the key can be extracted for person willing to target your client.

I would delegate the task of communicating with this API to your Application Server. You can put the key in your server and have your server communicate with this external API and relay the response to the client.

Edit: Another approach, which is less secure but more convenient is to obfuscate your code using something like proguard. See this page for flutter instruction on android app: https://flutter.io/android-release/

Solution 4 - Dart

You can use flutter_secure_storage from the oficial Flutter Packages

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPhilip MutuaView Question on Stackoverflow
Solution 1 - DartNoodlesView Answer on Stackoverflow
Solution 2 - DartRolando UrquizaView Answer on Stackoverflow
Solution 3 - DartGainzView Answer on Stackoverflow
Solution 4 - DartÁlvaro AgüeroView Answer on Stackoverflow