I want to store an api key on my flutter app. I was thinking about requesting the api key from the server on user registration, and then save it with flutter_secure_storage.
Is that a good way to get and store api keys?
As seen here.
The most secure way to keep your keys as secret, is to NEVER put them in your app because someone could decompile your app and get them, but if you really want to store them in the app the most recommended approach I have found is using text assets. In Flutter you just need to load your file containing your secret keys as if your were loading any other asset.
Create a file called secrets.json that will keep our secret API keys. And store it in the root directory of our project. Remember not to commit your secrets.json file to version control.
write an entry in pubspec.yaml pointing to our secret file.
assets:
- secrets.json
define the class that will keep our keys, let’s say it’s called Secret
class Secret {
final String apiKey; Secret({this.apiKey = ""});
factory Secret.fromJson(Map<String, dynamic> jsonMap) {
return new Secret(apiKey: jsonMap["api_key"]);
}
}
Then a SecretLoader
import 'dart:async' show Future;
import 'dart:convert' show json;
import 'package:flutter/services.dart' show rootBundle;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;
});
}
}
After that, you can just use your SecretLoader like this:
Future<Secret> secret = SecretLoader(secretPath: "secrets.json").load();
Definitely yes from me! It is a best way to store data in secure storage
flutter_secure_storage: ^4.2.0
I'm running into this same question on best practices for API keys in Flutter. I've read many responses across multiple stack posts. It seems that no matter what we do, someone dedicated enough will get the API key so we must turn our attention to limiting the actions of the API.
I'm using Algolia in my project so I'm going to use this service as an example. This service gives you multiple API keys. One of them is for "search only" and another is the ADMIN API key.
The Search Only API key comes with parameters that you can set to prevent API abuse and additionally only allows reads, and does not allow writes or deletes. The Search only API key is what we will expose in our front end and NEVER expose our Admin API key.
I will still follow best practices on utilizing gitIgnore and doing my best to prevent API compromise but from what I've gathered it seems the most effective method is at the API source. I hope this helps in some way.
Related
Dynamic links work great for 98% of our users. However, there are still a group of users which have difficulty with them or do not know how to use them.
I want to add a feature which would let users paste their link into the app, and then we extract the data from the link and handle it normally. This will also serve as a backup for when the links are down or misbehaving. It will also allow our customer service team to get data from a link when customers share them with us.
The problem is, there doesn't seem to be a way to manually pass in a dynamic link to retrieve the dynamic data.
Does anyone know how this can be achieved?
Here is my attempt at your question.
I am assuming what you mean by the dynamic data is the underlying deeplink along with the parameters associated with the deeplink.
void dynamicLinkToDeepLink(String dynamicLinkString) async {
final details = await FirebaseDynamicLinks.instance.getDynamicLink(Uri.parse(dynamicLinkString));
// your deep link can be accessed as follows
details!.link;
}
You have to safeguard the above code as you see fits when you use it. You will have to wrap FirebaseDynamicLinks.instance..... with a try catch block and you will also have to check if the value of the returned link is not null before acccessing details!.link
I am developing a Flutter mobile and web app to query data from Elasticsearch.
The Elastic App Search provides me a public search key which I would like my Flutter app to use to get data from my index.
All the examples e.g. https://pub.dev/packages/elastic_client do authenticate with basic auth and user/pass.
Are there any approaches or existing libraries which I may use with Flutter?
Currently I am stuck at the very beginning.
I successfully connected the "Search with Elastic App Search" AddOn in Firebase to update my Elastic documents when a document in my Cloud Firestore changes.
In my Flutter app I would like to only query the Elasic index. There is no need for insert, update nor delete.
Before, I used Algolia https://pub.dev/packages/algolia where I could set up e.g.
static const Algolia algolia = Algolia.init(
applicationId: '<my-application-id>',
apiKey: '<my-api-key>',
);
Now I am looking for something similar to connect to my Elastic App Search.
Do I have a general misunderstanding or did I miss anything in my plan?
There's a way to utilize public key with elastic_client, simply place api key as the authorization parameter:
Client.HttpTransport(url: 'https://ES_ENDPOINT:9243/', authorization: "ApiKey <BASE64_ENCODED_VALUE>");
The trick is to add "ApiKey" in front of the hashed/encoded value. Encoded value contains <id>:<api_key>, values generated via POST /_security/api_key (Create ES API key).
I have a purchased license at fusion charts. Fusion charts document says here... https://www.fusioncharts.com/dev/upgrading/license-activation that i have to use this function call for applying license...
FusionCharts.options.license({
key: 'KEY_GOES_HERE',
creditLabel: false,
});
if i put my key in that anyone visiting my website can easily take it from view -> source of browser. how do i avoid it ? It is simple HTML website.
You can use either of the followings :
Instead of passing the keys directly in JS code, pass them via the environment, application variables. And add the env file to gitignore
Use Obfuscation for the key and JS code being used for license activation.
You can store the value of the key in your database & and fetch the data value so that the end-user is unable to access it.
If you know the domain/sub-domains where charts will be used, you can restrict the license keys to those domains by sending a request to sales#fusioncharts.com
As far as I know, there is no way to completely hide it from the frontend. The reason for this is that even if the key is hidden in some way when the request is made, the information has to exist and so the key could be found by looking at the request data.
What you wish to protect against determines how you should go about it. If you would just like to hide it from being picked up by webscrapers, then I would imagine encrypting it and then decrypting it before you send would be sufficient.
If you would like to protect against anyone stealing it, then the only way is to have a server act as a proxy. You would make a call to an API which would then use your API key on the backend, away from the prying eyes of users. Your backend API would then just return to the user the response from fusioncharts.
I'm working in an Asp.Net Core 2 web api for files hosted at Google Cloud Storage. The files hosted there are not public, so I can't use the MediaLink property of the object. I tried to make a download endpoint using MemoryStream but when there are many users downloading large files at once I run into memory issues.
My question is: is there a way to create something link a one-time download link for a file or something similar?
I'm also trying to implement what's described in this link but I'd need to give the bearer token to the user. I can't do that.
Any tips?
Yes. Google Cloud Storage offers a feature called "signed URLs" that is what you described: a URL that is only good for a short while to download a single file. The idea is that you craft a download URL, then use the private key of a service account to "sign" the URL. Anyone holding that final URL can use it to act as that service account for the purpose of downloading that one object.
Take a look: https://cloud.google.com/storage/docs/access-control/#Signed-URLs
Writing code to generate the signed URL is a bit tricky, but the client libraries provide helper methods in several languages to do it for you. You can also generate one with the gsutil command: gsutil signurl -d 10m privatekey.p12 gs://bucket/foo
There is a code sample for generating he signed URLs programatically on their GitHub project: Signed URLs
I managed to Create it using C#. I'm posting here because this will be useful to someone else:
1 - Create your private key
2 - Create and UrlSigner:
private readonly UrlSigner _urlSigner;
2 - In your class constructor:
using (var stream = File.OpenRead(_googleSettings.StorageAuthJson))
{
_urlSigner = UrlSigner.FromServiceAccountData(stream);
}
_googleSettings.StorageAuthJson has the physical path of the json file you downloaded when creating your key.
3 - Method to get the URL:
public string GetSignedUrl(string bucketName, string objectName, TimeSpan duration) {
var url = _urlSigner.Sign(bucketName, objectName, duration, null);
return url;
}
I was trying out the new enhanced revocable sessions in Parse on my Android app. It works well when logging in or signing up via email password or facebook but doesn't work well for custom authentication, e.g. google+.
I'm currently logging in the user using the cloud code which also creates the new user when signing up. This does not create a new Session object, that means the new enhanced sessions are not used and it still uses the legacy sessions.
I pass the session token back to client where using the become method the user logs in but it's the legacy sessions.
This feels like the feature is not complete but I would really like to move to the new enhanced sessions with my app. Has anyone worked with them yet? Are there any workarounds using the REST API or by creating the sessions manually and handling them manually? I looked into the JS API but it says it's only read only.
Here's the Blog post on Enhanced Sessions.
Where should I go next?
Yes, I found a solution but it's a workaround, works for my case because I don't support signing up with user/password.
Basically, the solution (cloud code) in semi pseudo-code is:
Fetch the user with master key
Check if user.getSessionToken() has value
if it has, return the session token and do a user.become() in the client as usual
if it's not, here the workaround, do the following:
yourPreviousPromiseInOrderToChainThem.then(function(user)
password = new Buffer(24);
_.times(24, function(i) {
password.set(i, _.random(0, 255));
});
password = password.toString('base64')
user.setPassword(password);
return user.save();
}).then(function(user) {
return Parse.User.logIn(user.get('username'), password)
}).then(function(user) {
var sessionToken = user.getSessionToken();
// Return the session token to the client as you've been doing with legacy sessions
})
That means, I'm changing the user password each time in order to make a remote login and, of course, I know thist can't be applied to all cases, it's enough for app because I don't support login with user/password (only third party logins) but I understand that maybe it's not for all cases.
I got the idea from this official Parse example.
I don't like this solution because I think is not a workaround, it's a mega hack but I think there is no other way to do it currently (either Parse.com or Parse-Server)
If you find other workaround, please, share it :)