<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Carlo Loguercio</title>
    <description>The latest articles on Forem by Carlo Loguercio (@carlodotlog).</description>
    <link>https://forem.com/carlodotlog</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F841156%2F355ec82c-1376-4122-a7e0-43183613c778.jpeg</url>
      <title>Forem: Carlo Loguercio</title>
      <link>https://forem.com/carlodotlog</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/carlodotlog"/>
    <language>en</language>
    <item>
      <title>How to store login credentials, the right way in Flutter.</title>
      <dc:creator>Carlo Loguercio</dc:creator>
      <pubDate>Sun, 03 Apr 2022 15:38:26 +0000</pubDate>
      <link>https://forem.com/carlodotlog/how-to-store-login-credentials-the-right-way-in-flutter-32df</link>
      <guid>https://forem.com/carlodotlog/how-to-store-login-credentials-the-right-way-in-flutter-32df</guid>
      <description>&lt;p&gt;When we are asked to develop a login screen and there is a “remember me" check box or an auto-login feature, all we have to do is to save the login credentials, or some kind of token, into a local storage. So, the next time we come back into the app, we find the form already filled with our credentials or, better, an auto-login saves us from the boring login screen.&lt;/p&gt;

&lt;p&gt;It’s awesome, yes. But what about security?&lt;/p&gt;

&lt;p&gt;If we store the user’s credentials into SharedPreferences, we potentially expose this data to an attacker that, potentially, can steal them.&lt;/p&gt;

&lt;p&gt;Fortunately, the Flutter community is big enough to create a package that covers this scenario.&lt;/p&gt;

&lt;p&gt;There is a package, called &lt;a href="https://pub.dev/packages/flutter_secure_storage" rel="noopener noreferrer"&gt;flutter_secure_storage&lt;/a&gt; and created by GitHub user &lt;a href="https://github.com/mogol" rel="noopener noreferrer"&gt;mogol&lt;/a&gt;, that stores data into Keychains for iOS and uses AES encryption with Keystore for Android. Android version, from v5.0.0, it supports EncryptedSharedPreferences, too.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When upgrading from 4.2.1 to 5.0.0 you can migrate to EncryptedSharedPreferences by setting the encryptedSharedPreference parameter to true as explained below. This will automatically migrate all preferences. This however can’t be undone. If you try to disable encryptedSharedPreference after this, you won’t be able to read the values. You can only read those with encryptedSharedPreference enabled.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is a note for Android: this plugin is compatible only with Android SDK 18+, when Keystore was introduced.&lt;/p&gt;

&lt;p&gt;Now see how we can use this plugin for a login screen.&lt;/p&gt;




&lt;p&gt;This is the login page we’re going to create.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941262123%2FW6TMBKYyk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941262123%2FW6TMBKYyk.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you fill the form with credentials and push the Sign In button, you will store them into a secure storage. When you come back in-app you will find your credentials auto-filled in the form.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a simple login UI, with any kind of login business logic behind it. I won’t use any kind of state management, only the old good setState (). It’s only a simple code sample to show the usage of the package.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ok, let’s code.&lt;/p&gt;

&lt;p&gt;First of all, we need to add the package into the &lt;code&gt;pubspec.yaml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941263447%2FEMDtTI94s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941263447%2FEMDtTI94s.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, but... How &lt;code&gt;flutter_secure_storage&lt;/code&gt; works?&lt;/p&gt;

&lt;p&gt;As reported in the &lt;code&gt;README.md&lt;/code&gt;, all we have to do is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941264780%2FVRw7T6oL_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941264780%2FVRw7T6oL_.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s an extremely easy package, yes.&lt;/p&gt;

&lt;p&gt;As you can see, at &lt;strong&gt;line 4&lt;/strong&gt;, we create a storage that enables us to read and store data.&lt;/p&gt;

&lt;p&gt;At &lt;strong&gt;line 7&lt;/strong&gt;, we read and decrypt a String value identified by the &lt;code&gt;key&lt;/code&gt; label, or null if the &lt;code&gt;key&lt;/code&gt; is not in the storage. Remember: the &lt;code&gt;key&lt;/code&gt; shouldn’t be null.&lt;/p&gt;

&lt;p&gt;At &lt;strong&gt;line 19&lt;/strong&gt;, we store and encrypt a &lt;code&gt;value&lt;/code&gt; object identified by the &lt;code&gt;key&lt;/code&gt; label. If the &lt;code&gt;key&lt;/code&gt; was already in the storage, its associated &lt;code&gt;value&lt;/code&gt; is changed. If the &lt;code&gt;value&lt;/code&gt; is null, deletes the associated &lt;code&gt;value&lt;/code&gt; for the given &lt;code&gt;key&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For our use case we need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  the &lt;code&gt;FlutterSecureStorage&lt;/code&gt; storage instance;&lt;/li&gt;
&lt;li&gt;  two &lt;code&gt;TextEditingController&lt;/code&gt; associated with two &lt;code&gt;TextInputField&lt;/code&gt; widgets to gather user credentials;&lt;/li&gt;
&lt;li&gt;  a method to &lt;code&gt;write&lt;/code&gt; data into storage;&lt;/li&gt;
&lt;li&gt;  a method to &lt;code&gt;read&lt;/code&gt; data from storage;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let’s define the first two points :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941266073%2FFTC_pavpp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941266073%2FFTC_pavpp.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, we define the method &lt;code&gt;_onFormSubmit()&lt;/code&gt; to store the user credentials. This method is the action associated with the &lt;code&gt;Sing In&lt;/code&gt; button. The method will take care of saving the data in the storage only if the form is validated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941267320%2Fxrlo5sG3B.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941267320%2Fxrlo5sG3B.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, we define the method &lt;code&gt;_readFromStorage()&lt;/code&gt;. We call this method from the &lt;code&gt;initState()&lt;/code&gt;, in this way the information in the storage will be retrieved before the construction of our UI.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The initState() method is called from the framework when the State is created. (so it’s called only one time, before the UI is drawn).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941268592%2FFt95FbqUM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941268592%2FFt95FbqUM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this way, we get the behavior shown in the following screenshots.&lt;br&gt;&lt;br&gt;
At the first login, the user enters their credentials and presses the Sign In button.&lt;br&gt;&lt;br&gt;
Later, when he opens the app again, he will find his credentials already entered in the form.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941269903%2Fk948c1VaS.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941269903%2Fk948c1VaS.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941271218%2Fat1-bSyQxU.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1648941271218%2Fat1-bSyQxU.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will find the link to the repository on GitHub with the complete code below.&lt;/p&gt;

&lt;p&gt;Well done! These simple directions will allow you to add auto-login functionality to your app, but most importantly, the stored information will be encrypted in secure storage.&lt;br&gt;&lt;br&gt;
With these simple steps, your app will level up. :D&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;flutter_secure_storage is a very simple package that, in few simple steps enables us to save user's data, encrypted, in a secure storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s next?&lt;/strong&gt; You should extend this simple sample storing other user information, for example, the first name, so you can customize the “Welcome back” message.&lt;/p&gt;

&lt;p&gt;You can find the full example code on my GitHub repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/CarloDotLog/flutter_login_screen/tree/blog_post_branch" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub - CarloDotLog/flutter_login_screen at blog_post_branch&lt;/strong&gt;&lt;/a&gt;&lt;a href="https://github.com/CarloDotLog/flutter_login_screen/tree/blog_post_branch" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you so much for reading my article. Consider clicking the “clap” button to show me your interest and to encourage me to go on in my new adventure ^^&lt;/p&gt;




&lt;p&gt;If you are interested in other &lt;strong&gt;Flutter Security Tips&lt;/strong&gt;, you can read my other articles I’ve published on Medium.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@carlo.log/list/3cab906c71d3" rel="noopener noreferrer"&gt;&lt;strong&gt;Flutter Security Tips&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
 medium.com&lt;/a&gt;&lt;a href="https://medium.com/@carlo.log/list/3cab906c71d3" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What about me?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m Carlo and I’m a passionate Italian coder since 2009. I’m Java native speaker and I’ve never left the JAVA_HOME since I’ve met Dart and Flutter in late 2019.&lt;/p&gt;

&lt;p&gt;Follow me here on Dev.to to read more articles about Flutter and mobile development.&lt;/p&gt;

&lt;p&gt;You can find me also on &lt;a href="https://twitter.com/Carlo_log" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://github.com/CarloDotLog" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, or &lt;a href="https://www.linkedin.com/in/carlo-loguercio/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See you around and happy coding.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>security</category>
      <category>mobile</category>
    </item>
  </channel>
</rss>
