Many of us have Flutter projects hosted in public repositories, for example, when we maintain a library or package published in the Pub dependency manager, or also because we work on an Open Source project we may need (from the very beginning) to avoid having sensitive data hosted in the repository. I am referring to keys, tokens, and any other sensitive data encoded somewhere in the project uploaded to the repository.
It may seem that this does not affect private repositories, that the project partners are trustworthy people who will not leak company information, but poor repository management can allow access to any member of the company, and any member of the company receiving a successful hack can cause a catastrophe. This is what happened at a company I was working for some time ago. It received a cyber attack where the attacker allegedly had at least access to some of the company's repositories. This made me think that securing private repositories may give the impression at first glance that it is less necessary than securing public repositories. But as you just read, this happens more often than you might think.
Far from telling stories, let's start securing our repository.
Golden rule
No sensitive data has to be uploaded. This means that we cannot upload sensitive project data to the repository either as a file or in hardcoded form. It is a widespread practice to have api keys as constants in some file or class of the project. Even users and passwords!
How can we avoid this?
The easiest way is to work with .env files. These files contain credentials in key-value format for services used by the program they’re building. They’re meant to be stored locally and not be uploaded to code repositories online for everyone to read. Each developer in a team typically carries one or more .env files.
To do so, we will use the flutter_dotenv dependency by following the steps below:
1. Create the .env file in the root of the project.
2. Before modifying the .env file, let's add it to the .gitignore file so that it cannot be uploaded by accident. This is a snapshot of my .gitignore file:
Important note here. If we use any Google service (Firebase, etc...) we have to add them to the .gitignore file (from 48 to 50 line). An example of this would be the following:
As you can see, they were added them into .gitignore file using a regex. The point is there is sensitive information inside:
3. Now we need to add the new
.env file as an asset within the
pubspec.yaml 4. Finally, in the main.dart file we must load the .env file so that we can access our key/value dictionary (.env file), inside our code.
In my case, I created a custom function invoked inside the
main function that prints by console if the loading was not successful.
Well, it will depend a bit on your needs. If you are using Firebase, you will need to take an extra step. FlutterFire CLI, the Firebase tool generates a firebase_options.dart file that you need to protect. We have two options, both with their pros and cons.
Option 1: Add this auto-generated file to the .gitignore. As you can imagine this has a big disadvantage, that the importing will fail when someone new downloads the project.
Option 2: Modify the autogenerated file to load this information from the .env file, because although it will be deleted when it is autogenerated again, there is no reason to autogenerate it continuously and in practice it will not be done very often.
We will use option 2. Besides preferring this option, we can see how to add data to the .env file.
First, we will modify the firebase_options.dart file. For each platform we have a method with the sensitive data that we have to modify using our .env file:
Within the file we will use key-value pairs separated by line breaks between them.
As you can see, and for obvious reasons, it is much better to have our project and repository secured. We recently discussed how to set up
CI in a flutter project.
Securing and accessing to sensitive data within the CI system has not been addressed so as not to make this guide too long. I will soon create a specific post for this point.
See you in the next post, greetings!
Comments
Post a Comment