Reputation: 3313
I am using googleapis services in my flutter app which requires some credentials in JSON format. What is the best way to store this credentials in my App?
Can I keep a JSON file in my asset folder and read it in my main function?
Or should I hardcode the credentials in my main function? I'm new to flutter development.
My code looks like the following
import 'package:googleapis/storage/v1.dart';
import 'package:googleapis_auth/auth_io.dart';
final _credentials = new ServiceAccountCredentials.fromJson(r'''
{
"private_key_id": ...,
"private_key": ...,
"client_email": ...,
"client_id": ...,
"type": "service_account"
}
''');
const _SCOPES = const [StorageApi.DevstorageReadOnlyScope];
void main() {
clientViaServiceAccount(_credentials, _SCOPES).then((http_client) {
var storage = new StorageApi(http_client);
storage.buckets.list('dart-on-cloud').then((buckets) {
print("Received ${buckets.items.length} bucket names:");
for (var file in buckets.items) {
print(file.name);
}
});
});
}
Where I should keep the following credentials:
{
"private_key_id": ...,
"private_key": ...,
"client_email": ...,
"client_id": ...,
"type": "service_account"
}
I don't think hardcoding like above is a good idea.
I think this should work:https://medium.com/@sokrato/storing-your-secret-keys-in-flutter-c0b9af1c0f69
Thanks.
Upvotes: 23
Views: 28113
Reputation: 28552
Comment: I dont see how Robin actually answers the question. The original poster needs the application to have credentials to access an API. Using secure key storage does not give the application any data so it still can't access the API. If you add the file in your project, then secure key storage does not secure the file in any way.
Environment variables: I suggest using environment variables for variables that change depending on the environment: you might have 2 API_KEYS because you have a production and testing environment. However, attackers with your app can still steal this by just 'man-in-the-middling'-ing your requests, for example, using proxyman.A ttackers can sniff traffic or decompile your application to steal API_KEYS and use them in their own projects, exploits or cryptomining. Therefore, if you’re using environment variables, ensure your API keys are not that powerful. Some API providers will allow you to limit the power of that key.
Backend: So, if the API_KEY is powerful and unrestricted, then it should not be used on the application at all. It should be in your backend, which calls external APIs on behalf of clients. You could host a server to do this, or use serverless functions (e.g. AWS Lambda, GCP cloud functions, Azure functions, Firebase cloud functions, and lots more).
It depends on your threat model: what kind of threats you think is possible against your app. In my case, I'm not that bothered about someone decompiling my hackathon project to steal a weather API_KEY that I got for free, but I am afraid that some github crawlers or the api provider finding this api_key and disabling it (This happened to my friend with her Google Cloud Platform service account credentials). So, I am using environment variables.
Upvotes: 21
Reputation: 1101
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
/*
* Example of a secure store as a Mixin
* Usage:
import '../mixins/secure_store_mixin.dart';
MyClass extends StatelessWidget with SecureStoreMixin {
exampleSet(){
setSecureStore('jwt', 'jwt-token-data');
}
exampleGet(){
getSecureStore('jwt', (token) { print(token); });
}
}
*/
class SecureStoreMixin{
final secureStore = new FlutterSecureStorage();
void setSecureStore(String key, String data) async {
await secureStore.write(key: key, value: data);
}
void getSecureStore(String key, Function callback) async {
await secureStore.read(key: key).then(callback);
}
}
Note: Extend by adding more methods:
Map<String, String> allValues = await secureStore.readAll();
await secureStore.delete(key: key);
await secureStore.deleteAll();
Upvotes: 3
Reputation: 2517
For storing sensitive information like credentials you should use the Keychain unter iOS and the Keystore under Android.
There is a perfect library for that called flutter_secure_storage
.
Here's how to use that:
// Create storage
final storage = new FlutterSecureStorage();
// Store password
await storage.write(key: "password", value: "my-secret-password");
// Read value
String myPassword = await storage.read(key: "password");
To use it add flutter_secure_storage: 3.2.1+1
to you pubspec.yaml
and run flutter packages get
in a terminal.
Here is the package and a more detailled example on how to use it: https://pub.dartlang.org/packages/flutter_secure_storage
Upvotes: 29