{"componentChunkName":"component---src-pages-markdown-remark-fields-slug-js","path":"/engineering/guest-post/authenticating-flutter-apps/","result":{"data":{"markdownRemark":{"id":"a2592925-b065-5c8a-9549-069c4851c3e4","excerpt":"Introduction User authentication is the process of validating a user's identity to ensure that they are who they claim to be. Implementing user authentication…","html":"<h2 id=\"introduction\" style=\"position:relative;\"><a href=\"#introduction\" aria-label=\"introduction permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Introduction</h2>\n<p>User authentication is the process of validating a user's identity to ensure that they are who they claim to be. Implementing user authentication in your application is critical to prevent unauthorized users from accessing sensitive information.</p>\n<p>This tutorial focuses on implementing user authentication and registration in Flutter applications using the LoginRadius API.</p>\n<h2 id=\"prerequisites\" style=\"position:relative;\"><a href=\"#prerequisites\" aria-label=\"prerequisites permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Prerequisites</h2>\n<p>If you wish to follow along with this tutorial, you must have the following set up:</p>\n<ul>\n<li><a href=\"https://accounts.loginradius.com/auth.aspx\">Sign up for a free LoginRadius developer account</a></li>\n<li>Any IDE that has <a href=\"https://docs.flutter.dev/get-started/install\">Flutter SDK</a> installed (i.e., <a href=\"https://developer.android.com/studio\">Android Studio</a>, <a href=\"https://code.visualstudio.com/\">VSCode</a>)</li>\n<li>A basic understanding of <a href=\"https://dart.dev/\">Dart</a> and <a href=\"https://flutter.dev/\">Flutter</a></li>\n</ul>\n<p>This tutorial is verified with Flutter v2.5.1 and Android Studio v3.5.</p>\n<h2 id=\"getting-started-with-loginradius\" style=\"position:relative;\"><a href=\"#getting-started-with-loginradius\" aria-label=\"getting started with loginradius permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Getting Started with LoginRadius</h2>\n<h3 id=\"what-is-loginradius\" style=\"position:relative;\"><a href=\"#what-is-loginradius\" aria-label=\"what is loginradius permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What is LoginRadius?</h3>\n<p>LoginRadius is a cloud-based, SaaS Customer Identity and Access Management (CIAM) platform that provides developers and businesses simplified and robust features for managing customer identity, privacy, and access. LoginRadius offers high-level, secure, and well-documented APIs for integrating User Authentication and Single Sign-on (SSO) into your application.</p>\n<h3 id=\"why-use-loginradius\" style=\"position:relative;\"><a href=\"#why-use-loginradius\" aria-label=\"why use loginradius permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Why use LoginRadius?</h3>\n<p>LoginRadius offers:</p>\n<ul>\n<li>A scalable infrastructure</li>\n<li>Built-in security measures to improve user account security and safe user data management</li>\n<li>Advanced login options such as Social SSO and Passwordless Login to improve the user experience</li>\n<li>SDKs and well-documented APIs for seamless integration into your application</li>\n</ul>\n<p>So, with everything out of the way, let's get started.</p>\n<h2 id=\"setting-up-loginradius-for-your-application\" style=\"position:relative;\"><a href=\"#setting-up-loginradius-for-your-application\" aria-label=\"setting up loginradius for your application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Setting Up LoginRadius for Your Application</h2>\n<p>After creating an account with LoginRadius, it sets up a free app for you. This is the app in which you would integrate the LoginRadius API with Flutter. Here my app name is “tayy”.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 48.15384615384615%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABOElEQVQoz41S206EMBDlG/0c/8LE//DNHzAx8WXfNsYHN1lB2QVBoAVKWzjOcFkLi66TnKSdtmfOnKn39lmgEAK67SCUxW/Rdd0MeW1QawtZlvReQkgJpRS89CvD+0eILC+gjYHW2sGwN5RfErYto+VSPSzd2fsBPE42TUPQM7LmAiFGxJVBKDXKxuAQ+PD+ao+LDSrOW55yt5sDrh8CbCOJ7c4fFE7gC6wmy/MeFfkjyRtr7YlgWXiK1hpc3b3Ac6sNBxZxkuKYZLCUUnUN4xCuqeQVF7153P0QTsEHgqaeFwJlrVBV1ZnCGdm45qJH9pATliZWKHMi5G9g2Ts648m7Pq4Y3iuk1pDE0UDIUGZ4xI+FLGnKpifnKS+VudGOude0wmYfrbTsDIg/ak0e/ofwKZS4fw7xDUR5D2J55RUqAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"LoginRadius App Screen\"\n        title=\"LoginRadius App Screen\"\n        src=\"/static/33c5259fc16bb88fb1bb410700db0df3/e5715/app_window.png\"\n        srcset=\"/static/33c5259fc16bb88fb1bb410700db0df3/a6d36/app_window.png 650w,\n/static/33c5259fc16bb88fb1bb410700db0df3/e5715/app_window.png 768w,\n/static/33c5259fc16bb88fb1bb410700db0df3/ad00e/app_window.png 1366w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Next, you need to obtain your LoginRadius API credentials. To do so, login to your Dashboard and navigate to the <code>Configuration</code> tab in the sidebar menu. You will find your API credentials under the <code>API Key and Secret</code> section. Copy and store your <strong>APP Name</strong>, <strong>API Key</strong>, and <strong>API Secret</strong> somewhere safe and easily accessible.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 48.15384615384615%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABuUlEQVQoz32SX2sTQRTFxzcJRWmVPtmCoERrq2kbH8TEtLUQxLd+t36F9q3xKXnyAyi0r1qCQtJgyJ/9k52dndmd3RzvTBKa0NALh91ZZn5z7tnLnpVO8KT4FexFGReN7zClEg2uNHSaIiOlS+SJGEIlCHmIURAg4BxSKbD14hes7VbBnn/AWa1ugUPHheN6UHFsD2udWvhMk28aiVGSkDSUitG+6YA9ffcZj7YqYBv7OP/WsMBefwjXH0FKiZigim5W9jmTssBZjUlpmqHbuSGHe1UCHoBtvieHE6CIIuvEbh6Pbw/S+zKZMl1cNVvksHCMx28MsIizqcP+gBx6HsJQkEIrTjIZGXfp3GUTkUNyfFK7Blt7e4SVV58WHHICxZSNmgIktWnWaZbd41Dj9GcbbHXnCKvbhxY4y3DgkDshwUUEGUk0HYGBvBvB/NpcGHou2MOXH5HLlxaA/aFLo8Dh+QE4jUPHlxBJtjRH069FZhq+64Dl8mWsvK4sAHsDBwG17QchBGX3143w21VLHWbT9R9P4rLVpwwLVazTYD+Ym8ORAUlFf3uSYWdEm3vRvcAf/0LUf3XxH7RzuT2/O2SbAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"LoginRadius Configuration Tab\"\n        title=\"LoginRadius Configuration Tab\"\n        src=\"/static/9ac569a072de64231421e73c6c7bb31c/e5715/configuration_tab.png\"\n        srcset=\"/static/9ac569a072de64231421e73c6c7bb31c/a6d36/configuration_tab.png 650w,\n/static/9ac569a072de64231421e73c6c7bb31c/e5715/configuration_tab.png 768w,\n/static/9ac569a072de64231421e73c6c7bb31c/ad00e/configuration_tab.png 1366w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<h2 id=\"integrating-loginradius-api-with-your-flutter-application\" style=\"position:relative;\"><a href=\"#integrating-loginradius-api-with-your-flutter-application\" aria-label=\"integrating loginradius api with your flutter application permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Integrating LoginRadius API with Your Flutter Application.</h2>\n<h3 id=\"step-1-create-a-new-flutter-project\" style=\"position:relative;\"><a href=\"#step-1-create-a-new-flutter-project\" aria-label=\"step 1 create a new flutter project permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 1: Create a New Flutter project</h3>\n<p>Create a new Flutter project and navigate to the folder of the application by running the following commands in your terminal:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">flutter create loginradius_example</span>\n<span class=\"grvsc-line\">cd loginradius_example</span></code></pre>\n<h3 id=\"step-2-install-dependencies\" style=\"position:relative;\"><a href=\"#step-2-install-dependencies\" aria-label=\"step 2 install dependencies permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 2: Install Dependencies</h3>\n<p>Next, you need to install the <code>dio</code> package as a dependency in our project. The <code>dio</code> package is a powerful HTTP client used for making network requests.</p>\n<p>Run the following command to get the newest version of the <code>dio</code> package in your project.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">flutter pub add dio</span></code></pre>\n<p>Then, install the dependency by running <code>flutter pub get</code> in your terminal.</p>\n<h3 id=\"project-structure\" style=\"position:relative;\"><a href=\"#project-structure\" aria-label=\"project structure permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Project Structure</h3>\n<p>The project is being structured in this order:</p>\n<p><img src=\"/b063fac3cc95c21f1d7327d989a883ef/folder-structure.png\" alt=\"Folder Structure\"></p>\n<ul>\n<li>Core (contains a class that handles network requests)</li>\n<li>Screens (the UI of our app)</li>\n<li>Utils (helper components)</li>\n</ul>\n<h3 id=\"step-3-setting-up-the-api-client-class\" style=\"position:relative;\"><a href=\"#step-3-setting-up-the-api-client-class\" aria-label=\"step 3 setting up the api client class permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 3: Setting up the API Client Class</h3>\n<p>Create a new dart file named <code>api_client.dart</code> and import the <code>dio</code> package into the file, as follows:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">import &#39;package:dio/dio.dart&#39;;</span></code></pre>\n<p>Now let’s create a class named <code>ApiClient</code> and initialize the <code>Dio</code> object in it. The <code>ApiClient</code> class will contain several methods for making network requests based on your features, including User Registration, User Login, Get User Profile Data, and User Logout.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">import &#39;package:dio/dio.dart&#39;;</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">class ApiClient {</span>\n<span class=\"grvsc-line\">   final Dio _dio = Dio();</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">    Future&lt;Response&gt; registerUser() async {</span>\n<span class=\"grvsc-line\">        //IMPLEMENT USER REGISTRATION</span>\n<span class=\"grvsc-line\">    }</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">    Future&lt;Response&gt; login() async {</span>\n<span class=\"grvsc-line\">        //IMPLEMENT USER LOGIN</span>\n<span class=\"grvsc-line\">    }</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">    Future&lt;Response&gt; getUserProfileData() async {</span>\n<span class=\"grvsc-line\">        //GET USER PROFILE DATA</span>\n<span class=\"grvsc-line\">    }</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">    Future&lt;Response&gt; logout() async {</span>\n<span class=\"grvsc-line\">        //IMPLEMENT USER LOGOUT</span>\n<span class=\"grvsc-line\">     }</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<h3 id=\"step-4-implement-user-registration\" style=\"position:relative;\"><a href=\"#step-4-implement-user-registration\" aria-label=\"step 4 implement user registration permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 4: Implement User Registration</h3>\n<p>Before implementing the user registration functionality, you must first <a href=\"https://www.loginradius.com/developers/\">obtain the user registration endpoint URL from the LoginRadius API Docs</a>.</p>\n<p>After retrieving the endpoint URL, you need to send a POST request to the endpoint using the <code>Dio</code> package by passing in:</p>\n<ul>\n<li>the <code>apiKey</code> you obtained earlier as a query parameter;</li>\n<li>the <code>userData</code> as the request body; and,</li>\n<li>the <code>SOTT</code> key as a header, as shown below.</li>\n</ul>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">class ApiClient {</span>\n<span class=\"grvsc-line\">       //...</span>\n<span class=\"grvsc-line\">       Future&lt;Response&gt; registerUser(Map&lt;String, dynamic&gt;? userData) async {</span>\n<span class=\"grvsc-line\">        try {</span>\n<span class=\"grvsc-line\">          Response response = await _dio.post(</span>\n<span class=\"grvsc-line\">              &#39;https://api.loginradius.com/identity/v2/auth/register&#39;,  //ENDPONT URL</span>\n<span class=\"grvsc-line\">              data: userData, //REQUEST BODY</span>\n<span class=\"grvsc-line\">              queryParameters: {&#39;apikey&#39;: &#39;YOUR_API_KEY&#39;},  //QUERY PARAMETERS</span>\n<span class=\"grvsc-line\">              options: Options(headers: {&#39;X-LoginRadius-Sott&#39;: &#39;YOUR_SOTT_KEY&#39;, //HEADERS</span>\n<span class=\"grvsc-line\">          }));</span>\n<span class=\"grvsc-line\">          //returns the successful json object</span>\n<span class=\"grvsc-line\">          return response.data;</span>\n<span class=\"grvsc-line\">        } on DioError catch (e) {</span>\n<span class=\"grvsc-line\">          //returns the error object if there is</span>\n<span class=\"grvsc-line\">          return e.response!.data;</span>\n<span class=\"grvsc-line\">        }</span>\n<span class=\"grvsc-line\">      }</span>\n<span class=\"grvsc-line\">    }</span></code></pre>\n<h3 id=\"step-5-implement-user-login\" style=\"position:relative;\"><a href=\"#step-5-implement-user-login\" aria-label=\"step 5 implement user login permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 5: Implement User Login</h3>\n<p>The below code snippet shows how you’ll send a POST request to the LoginRadius login endpoint URL <code>https://api.loginradius.com/identity/v2/auth/login</code>, passing in your <code>apiKey</code> as a query parameter and the <code>email</code> and <code>password</code> of the user as the request body.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">class ApiClient {</span>\n<span class=\"grvsc-line\">       //...</span>\n<span class=\"grvsc-line\">       Future&lt;Response&gt; login(String email, String password) async {</span>\n<span class=\"grvsc-line\">        try {</span>\n<span class=\"grvsc-line\">          Response response = await _dio.post(</span>\n<span class=\"grvsc-line\">            &#39;https://api.loginradius.com/identity/v2/auth/login&#39;,</span>\n<span class=\"grvsc-line\">            data: {</span>\n<span class=\"grvsc-line\">              &#39;email&#39;: email,</span>\n<span class=\"grvsc-line\">              &#39;password&#39;: password</span>\n<span class=\"grvsc-line\">            },</span>\n<span class=\"grvsc-line\">            queryParameters: {&#39;apikey&#39;: &#39;YOUR_API_KEY&#39;},</span>\n<span class=\"grvsc-line\">          );</span>\n<span class=\"grvsc-line\">          //returns the successful user data json object</span>\n<span class=\"grvsc-line\">          return response.data;</span>\n<span class=\"grvsc-line\">        } on DioError catch (e) {</span>\n<span class=\"grvsc-line\">          //returns the error object if any</span>\n<span class=\"grvsc-line\">          return e.response!.data;</span>\n<span class=\"grvsc-line\">        }</span>\n<span class=\"grvsc-line\">      }</span>\n<span class=\"grvsc-line\">    }</span></code></pre>\n<h3 id=\"step-6-get-user-profile-data\" style=\"position:relative;\"><a href=\"#step-6-get-user-profile-data\" aria-label=\"step 6 get user profile data permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 6: Get User Profile Data</h3>\n<p>To retrieve the user profile details, send a <code>GET</code> request to the Read Profile Endpoint URL <code>https://api.loginradius.com/identity/v2/auth/account</code>, passing in your <code>apiKey</code> as a query parameter and the user's access token as the header.</p>\n<blockquote>\n<p>The user’s access token is gotten from the successful response object of the User Login endpoint.</p>\n</blockquote>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">class ApiClient {</span>\n<span class=\"grvsc-line\">       //...</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">       Future&lt;Response&gt; getUserProfileData(String accesstoken) async {</span>\n<span class=\"grvsc-line\">        try {</span>\n<span class=\"grvsc-line\">          Response response = await _dio.get(</span>\n<span class=\"grvsc-line\">            &#39;https://api.loginradius.com/identity/v2/auth/account&#39;,</span>\n<span class=\"grvsc-line\">            queryParameters: {&#39;apikey&#39;: &#39;YOUR_API_KEY&#39;},</span>\n<span class=\"grvsc-line\">            options: Options(</span>\n<span class=\"grvsc-line\">              headers: {</span>\n<span class=\"grvsc-line\">                &#39;Authorization&#39;: &#39;Bearer ${YOUR_ACCESS_TOKEN}&#39;,</span>\n<span class=\"grvsc-line\">              },</span>\n<span class=\"grvsc-line\">            ),</span>\n<span class=\"grvsc-line\">          );</span>\n<span class=\"grvsc-line\">          return response.data;</span>\n<span class=\"grvsc-line\">        } on DioError catch (e) {</span>\n<span class=\"grvsc-line\">          return e.response!.data;</span>\n<span class=\"grvsc-line\">        }</span>\n<span class=\"grvsc-line\">    }</span></code></pre>\n<h3 id=\"step-7-implement-user-logout\" style=\"position:relative;\"><a href=\"#step-7-implement-user-logout\" aria-label=\"step 7 implement user logout permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Step 7: Implement User Logout</h3>\n<p>Finally, to implement the user logout functionality, you would send a <code>GET</code> request to the Invalidate User Access Token endpoint URL <code>https://api.loginradius.com/identity/v2/auth/access_token/InValidate</code>. This API call invalidates the user's active access token, requiring them to re-authenticate if they want to access their data.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">class ApiClient {</span>\n<span class=\"grvsc-line\">       //...</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">      Future&lt;Response&gt; logout(String accessToken) async {</span>\n<span class=\"grvsc-line\">        try {</span>\n<span class=\"grvsc-line\">          Response response = await _dio.get(</span>\n<span class=\"grvsc-line\">            &#39;https://api.loginradius.com/identity/v2/auth/access_token/InValidate&#39;,</span>\n<span class=\"grvsc-line\">            queryParameters: {&#39;apikey&#39;: ApiSecret.apiKey},</span>\n<span class=\"grvsc-line\">            options: Options(</span>\n<span class=\"grvsc-line\">              headers: {&#39;Authorization&#39;: &#39;Bearer $accessToken&#39;},</span>\n<span class=\"grvsc-line\">            ),</span>\n<span class=\"grvsc-line\">          );</span>\n<span class=\"grvsc-line\">          return response.data;</span>\n<span class=\"grvsc-line\">        } on DioError catch (e) {</span>\n<span class=\"grvsc-line\">          return e.response!.data;</span>\n<span class=\"grvsc-line\">        }</span>\n<span class=\"grvsc-line\">      }</span>\n<span class=\"grvsc-line\">    }</span></code></pre>\n<p>That concludes the <code>ApiClient</code> class. Next, you'll build the UI for your Flutter application, making use of the methods you just created in the <code>ApiClient</code> class.</p>\n<h3 id=\"building-the-ui\" style=\"position:relative;\"><a href=\"#building-the-ui\" aria-label=\"building the ui permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Building the UI</h3>\n<p>Your Flutter application will consist of four screens, which include:</p>\n<ul>\n<li>Registration Screen</li>\n<li>Login Screen</li>\n<li>Home Screen</li>\n</ul>\n<p>Let’s begin by building the Registration Screen.</p>\n<h3 id=\"registration-screen\" style=\"position:relative;\"><a href=\"#registration-screen\" aria-label=\"registration screen permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Registration Screen</h3>\n<p>The <code>RegistrationScreen</code> has two <code>TextFormField</code> widgets that serve as our <code>email</code> and <code>password</code> fields, as well as an <code>ElevatedButton</code> to handle event submission, as shown in the code snippet below from the <code>register.dart</code> file.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"> //...</span>\n<span class=\"grvsc-line\">    @override</span>\n<span class=\"grvsc-line\">    Widget build(BuildContext context) {</span>\n<span class=\"grvsc-line\">      Scaffold(</span>\n<span class=\"grvsc-line\">          backgroundColor: Colors.blueGrey[200],</span>\n<span class=\"grvsc-line\">          body: Form(</span>\n<span class=\"grvsc-line\">            key: _formKey,</span>\n<span class=\"grvsc-line\">            child: SizedBox(</span>\n<span class=\"grvsc-line\">              width: size.width,</span>\n<span class=\"grvsc-line\">              height: size.height,</span>\n<span class=\"grvsc-line\">              child: Align(</span>\n<span class=\"grvsc-line\">                alignment: Alignment.center,</span>\n<span class=\"grvsc-line\">                child: Container(</span>\n<span class=\"grvsc-line\">                  width: size.width * 0.85,</span>\n<span class=\"grvsc-line\">                  padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 30),</span>\n<span class=\"grvsc-line\">                  decoration: BoxDecoration(</span>\n<span class=\"grvsc-line\">                    color: Colors.white,</span>\n<span class=\"grvsc-line\">                    borderRadius: BorderRadius.circular(20),</span>\n<span class=\"grvsc-line\">                  ),</span>\n<span class=\"grvsc-line\">                  child: SingleChildScrollView(</span>\n<span class=\"grvsc-line\">                    child: Column(</span>\n<span class=\"grvsc-line\">                      crossAxisAlignment: CrossAxisAlignment.start,</span>\n<span class=\"grvsc-line\">                      children: &lt;Widget&gt;[</span>\n<span class=\"grvsc-line\">                        const Center(</span>\n<span class=\"grvsc-line\">                          child: Text(</span>\n<span class=\"grvsc-line\">                            &quot;Register&quot;,</span>\n<span class=\"grvsc-line\">                            style: TextStyle(</span>\n<span class=\"grvsc-line\">                              fontSize: 30,</span>\n<span class=\"grvsc-line\">                              fontWeight: FontWeight.bold,</span>\n<span class=\"grvsc-line\">                            ),</span>\n<span class=\"grvsc-line\">                          ),</span>\n<span class=\"grvsc-line\">                        ),</span>\n<span class=\"grvsc-line\">                        SizedBox(height: size.height * 0.05),</span>\n<span class=\"grvsc-line\">                        TextFormField(</span>\n<span class=\"grvsc-line\">                          validator: (value) =&gt;</span>\n<span class=\"grvsc-line\">                              Validator.validateEmail(value ?? &quot;&quot;),</span>\n<span class=\"grvsc-line\">                          controller: emailController,</span>\n<span class=\"grvsc-line\">                          keyboardType: TextInputType.emailAddress,</span>\n<span class=\"grvsc-line\">                          decoration: InputDecoration(</span>\n<span class=\"grvsc-line\">                            hintText: &quot;Email&quot;,</span>\n<span class=\"grvsc-line\">                            isDense: true,</span>\n<span class=\"grvsc-line\">                            border: OutlineInputBorder(</span>\n<span class=\"grvsc-line\">                              borderRadius: BorderRadius.circular(10),</span>\n<span class=\"grvsc-line\">                            ),</span>\n<span class=\"grvsc-line\">                          ),</span>\n<span class=\"grvsc-line\">                        ),</span>\n<span class=\"grvsc-line\">                        SizedBox(height: size.height * 0.03),</span>\n<span class=\"grvsc-line\">                        TextFormField(</span>\n<span class=\"grvsc-line\">                          obscureText: _showPassword,</span>\n<span class=\"grvsc-line\">                          validator: (value) =&gt;</span>\n<span class=\"grvsc-line\">                              Validator.validatePassword(value ?? &quot;&quot;),</span>\n<span class=\"grvsc-line\">                          controller: passwordController,</span>\n<span class=\"grvsc-line\">                          keyboardType: TextInputType.visiblePassword,</span>\n<span class=\"grvsc-line\">                          decoration: InputDecoration(</span>\n<span class=\"grvsc-line\">                            hintText: &quot;Password&quot;,</span>\n<span class=\"grvsc-line\">                            isDense: true,</span>\n<span class=\"grvsc-line\">                            border: OutlineInputBorder(</span>\n<span class=\"grvsc-line\">                              borderRadius: BorderRadius.circular(10),</span>\n<span class=\"grvsc-line\">                            ),</span>\n<span class=\"grvsc-line\">                          ),</span>\n<span class=\"grvsc-line\">                        ),</span>\n<span class=\"grvsc-line\">                        SizedBox(height: size.height * 0.06),</span>\n<span class=\"grvsc-line\">                        Row(</span>\n<span class=\"grvsc-line\">                          mainAxisAlignment: MainAxisAlignment.center,</span>\n<span class=\"grvsc-line\">                          children: [</span>\n<span class=\"grvsc-line\">                            Expanded(</span>\n<span class=\"grvsc-line\">                              child: ElevatedButton(</span>\n<span class=\"grvsc-line\">                                onPressed: _handleRegister,</span>\n<span class=\"grvsc-line\">                                style: ElevatedButton.styleFrom(</span>\n<span class=\"grvsc-line\">                                    primary: Colors.indigo,</span>\n<span class=\"grvsc-line\">                                    shape: RoundedRectangleBorder(</span>\n<span class=\"grvsc-line\">                                        borderRadius: BorderRadius.circular(10)),</span>\n<span class=\"grvsc-line\">                                    padding: const EdgeInsets.symmetric(</span>\n<span class=\"grvsc-line\">                                        horizontal: 40, vertical: 15)),</span>\n<span class=\"grvsc-line\">                                child: const Text(</span>\n<span class=\"grvsc-line\">                                  &quot;Register&quot;,</span>\n<span class=\"grvsc-line\">                                  style: TextStyle(</span>\n<span class=\"grvsc-line\">                                    fontSize: 20,</span>\n<span class=\"grvsc-line\">                                    fontWeight: FontWeight.bold,</span>\n<span class=\"grvsc-line\">                                  ),</span>\n<span class=\"grvsc-line\">                                ),</span>\n<span class=\"grvsc-line\">                              ),</span>\n<span class=\"grvsc-line\">                            ),</span>\n<span class=\"grvsc-line\">                          ],</span>\n<span class=\"grvsc-line\">                        ),</span>\n<span class=\"grvsc-line\">                      ],</span>\n<span class=\"grvsc-line\">                    ),</span>\n<span class=\"grvsc-line\">                  ),</span>\n<span class=\"grvsc-line\">                ),</span>\n<span class=\"grvsc-line\">              ),</span>\n<span class=\"grvsc-line\">            ),</span>\n<span class=\"grvsc-line\">          ),</span>\n<span class=\"grvsc-line\">        );</span>\n<span class=\"grvsc-line\">    }</span>\n<span class=\"grvsc-line\">    //...</span></code></pre>\n<p>In the <code>onPressed</code> callback of the <code>ElevatedButton</code> widget, you'll handle the validation of your form data.</p>\n<p>If the form is validated, you pass your <code>userData</code> to the <code>registerUser</code> method from the <code>ApiClient</code> class for processing.</p>\n<p>If the response is an error, you show a snackbar with the error message. Otherwise, the user is redirected to the Login Screen.</p>\n<blockquote>\n<p>In the following example, you've provided only a few user attributes as <code>userData</code>. To view the complete list of user attributes, please look at the body parameters of the User Registration API here.</p>\n</blockquote>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">Future&lt;void&gt; _handleRegister() async {</span>\n<span class=\"grvsc-line\">    if (_formKey.currentState!.validate()) {</span>\n<span class=\"grvsc-line\">    //show snackbar to indicate loading</span>\n<span class=\"grvsc-line\">     ScaffoldMessenger.of(context).showSnackBar(SnackBar(</span>\n<span class=\"grvsc-line\">        content: const Text(&#39;Processing Data&#39;),</span>\n<span class=\"grvsc-line\">        backgroundColor: Colors.green.shade300,</span>\n<span class=\"grvsc-line\">      ));</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">   //the user data to be sent</span>\n<span class=\"grvsc-line\">    Map&lt;String, dynamic&gt; userData = {</span>\n<span class=\"grvsc-line\">      &quot;Email&quot;: [</span>\n<span class=\"grvsc-line\">        {</span>\n<span class=\"grvsc-line\">          &quot;Type&quot;: &quot;Primary&quot;,</span>\n<span class=\"grvsc-line\">          &quot;Value&quot;: emailController.text,</span>\n<span class=\"grvsc-line\">        }</span>\n<span class=\"grvsc-line\">      ],</span>\n<span class=\"grvsc-line\">      &quot;Password&quot;: passwordController.text,</span>\n<span class=\"grvsc-line\">      &quot;About&quot;: &#39;I am a new user :smile:&#39;,</span>\n<span class=\"grvsc-line\">      &quot;FirstName&quot;: &quot;Test&quot;,</span>\n<span class=\"grvsc-line\">      &quot;LastName&quot;: &quot;Account&quot;,</span>\n<span class=\"grvsc-line\">      &quot;BirthDate&quot;: &quot;10-12-1985&quot;,</span>\n<span class=\"grvsc-line\">      &quot;Gender&quot;: &quot;M&quot;,</span>\n<span class=\"grvsc-line\">    };</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">    //get response from ApiClient</span>\n<span class=\"grvsc-line\">    dynamic res = await _apiClient.registerUser(userData);</span>\n<span class=\"grvsc-line\">    ScaffoldMessenger.of(context).hideCurrentSnackBar();</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">    //checks if there is no error in the response body.</span>\n<span class=\"grvsc-line\">    //if error is not present, navigate the users to Login Screen.</span>\n<span class=\"grvsc-line\">    if (res[&#39;ErrorCode&#39;] == null) {</span>\n<span class=\"grvsc-line\">      Navigator.push(context,</span>\n<span class=\"grvsc-line\">          MaterialPageRoute(builder: (context) =&gt; const LoginScreen()));</span>\n<span class=\"grvsc-line\">    } else {</span>\n<span class=\"grvsc-line\">     //if error is present, display a snackbar showing the error messsage</span>\n<span class=\"grvsc-line\">      ScaffoldMessenger.of(context).showSnackBar(SnackBar(</span>\n<span class=\"grvsc-line\">        content: Text(&#39;Error: ${res[&#39;Message&#39;]}&#39;),</span>\n<span class=\"grvsc-line\">        backgroundColor: Colors.red.shade300,</span>\n<span class=\"grvsc-line\">      ));</span>\n<span class=\"grvsc-line\">    }</span>\n<span class=\"grvsc-line\">  }</span>\n<span class=\"grvsc-line\">}</span></code></pre>\n<h3 id=\"login-screen\" style=\"position:relative;\"><a href=\"#login-screen\" aria-label=\"login screen permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Login Screen</h3>\n<p>The <code>LoginScreen</code> UI code is similar to the <code>RegistrationScreen</code> in that it also has two <code>TextFormField</code> widgets that serve as our <code>email</code> and <code>password</code> fields, as well as an <code>ElevatedButton</code> to handle event submission. So, for the sake of brevity, I’ll be leaving out the <code>LoginScreen</code> UI code and focusing mainly on the code to be written in the <code>ElevatedButton</code> onPressed callback in the <code>login_screen.dart</code> file.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">//...</span>\n<span class=\"grvsc-line\">    //...</span>\n<span class=\"grvsc-line\">       Future&lt;void&gt; loginUsers() async {</span>\n<span class=\"grvsc-line\">        if (_formKey.currentState!.validate()) {</span>\n<span class=\"grvsc-line\">          //show snackbar to indicate loading</span>\n<span class=\"grvsc-line\">          ScaffoldMessenger.of(context).showSnackBar(SnackBar(</span>\n<span class=\"grvsc-line\">            content: const Text(&#39;Processing Data&#39;),</span>\n<span class=\"grvsc-line\">            backgroundColor: Colors.green.shade300,</span>\n<span class=\"grvsc-line\">          ));</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">          //get response from ApiClient</span>\n<span class=\"grvsc-line\">          dynamic res = await _apiClient.login(</span>\n<span class=\"grvsc-line\">            emailController.text,</span>\n<span class=\"grvsc-line\">            passwordController.text,</span>\n<span class=\"grvsc-line\">          );</span>\n<span class=\"grvsc-line\">          ScaffoldMessenger.of(context).hideCurrentSnackBar();</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">          //if there is no error, get the user&#39;s accesstoken and pass it to HomeScreen</span>\n<span class=\"grvsc-line\">          if (res[&#39;ErrorCode&#39;] == null) {</span>\n<span class=\"grvsc-line\">            String accessToken = res[&#39;access_token&#39;];</span>\n<span class=\"grvsc-line\">            Navigator.push(</span>\n<span class=\"grvsc-line\">                context,</span>\n<span class=\"grvsc-line\">                MaterialPageRoute(</span>\n<span class=\"grvsc-line\">                    builder: (context) =&gt; HomeScreen(accesstoken: accessToken)));</span>\n<span class=\"grvsc-line\">          } else {</span>\n<span class=\"grvsc-line\">          //if an error occurs, show snackbar with error message</span>\n<span class=\"grvsc-line\">          ScaffoldMessenger.of(context).showSnackBar(SnackBar(</span>\n<span class=\"grvsc-line\">            content: Text(&#39;Error: ${res[&#39;Message&#39;]}&#39;),</span>\n<span class=\"grvsc-line\">            backgroundColor: Colors.red.shade300,</span>\n<span class=\"grvsc-line\">          ));</span>\n<span class=\"grvsc-line\">          }</span>\n<span class=\"grvsc-line\">        }</span>\n<span class=\"grvsc-line\">      }</span>\n<span class=\"grvsc-line\">    //...</span></code></pre>\n<p>The code snippet above is a method that first validates the form before passing the <code>email</code> and <code>password</code> values to the <code>login</code> method from the <code>ApiClient</code> class for handling.</p>\n<p>If the response is successful, you obtain the user’s <code>access_token</code> from the response data and pass it over to the <code>HomeScreen</code>. Otherwise, you display a snackbar with the error message that occurred.</p>\n<p>Then, you pass the <code>loginUsers</code> method you created above to the <code>onPressed</code> property of the <code>ElevatedButton</code> widget in the <code>LoginScreen</code>, as shown below.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">    ElevatedButton(</span>\n<span class=\"grvsc-line\">        onPressed: loginUsers, //&lt;--</span>\n<span class=\"grvsc-line\">        style: ElevatedButton.styleFrom(</span>\n<span class=\"grvsc-line\">        primary: Colors.indigo,</span>\n<span class=\"grvsc-line\">        shape: RoundedRectangleBorder(</span>\n<span class=\"grvsc-line\">               borderRadius: BorderRadius.circular(10)),</span>\n<span class=\"grvsc-line\">               padding: const EdgeInsets.symmetric(</span>\n<span class=\"grvsc-line\">                        horizontal: 40, vertical: 15)),</span>\n<span class=\"grvsc-line\">        child: const Text(&quot;Login&quot;,</span>\n<span class=\"grvsc-line\">            style: TextStyle(</span>\n<span class=\"grvsc-line\">                fontSize: 20,</span>\n<span class=\"grvsc-line\">                fontWeight: FontWeight.bold,</span>\n<span class=\"grvsc-line\">            ),</span>\n<span class=\"grvsc-line\">           ),</span>\n<span class=\"grvsc-line\">         ),</span>\n<span class=\"grvsc-line\">       ),</span></code></pre>\n<p>Next, you need to provide a screen that reveals the user's profile data when they successfully log in, and the <code>HomeScreen</code> is there to do so.</p>\n<h3 id=\"home-screen\" style=\"position:relative;\"><a href=\"#home-screen\" aria-label=\"home screen permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Home Screen</h3>\n<p>The <code>HomeScreen</code> displays the user’s profile details using a <code>FutureBuilder</code> widget that accepts a future <code>getUserData</code>.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">      Future&lt;Map&lt;String, dynamic&gt;&gt; getUserData() async {</span>\n<span class=\"grvsc-line\">        dynamic userRes;</span>\n<span class=\"grvsc-line\">        userRes = await _apiClient.getUserProfileData(widget.accesstoken);</span>\n<span class=\"grvsc-line\">        return userRes;</span>\n<span class=\"grvsc-line\">      }</span></code></pre>\n<p>The <code>getUserData</code> method above is used to retrieve details of a user by passing in the <code>access_token</code> obtained earlier from the <code>LoginScreen</code> to the <code>ApiClient</code> <code>getUserProfileData</code> method.</p>\n<p>To display the result of your <code>getUserData</code> method on our screen, use a <code>FutureBuilder</code> widget. The code snippet below shows how to use the <code>FutureBuilder</code> to get the results of the <code>getUserData</code> future in the <code>home.dart</code> file.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">    class HomeScreen extends StatefulWidget {</span>\n<span class=\"grvsc-line\">      final String accesstoken;</span>\n<span class=\"grvsc-line\">      const HomeScreen({Key? key, required this.accesstoken}) : super(key: key);</span>\n<span class=\"grvsc-line\">      @override</span>\n<span class=\"grvsc-line\">      State&lt;HomeScreen&gt; createState() =&gt; _HomeScreenState();</span>\n<span class=\"grvsc-line\">    }</span>\n<span class=\"grvsc-line\">    class _HomeScreenState extends State&lt;HomeScreen&gt; {</span>\n<span class=\"grvsc-line\">      //instance of ApiClient class</span>\n<span class=\"grvsc-line\">      final ApiClient _apiClient = ApiClient();</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">      //get user data from ApiClient</span>\n<span class=\"grvsc-line\">      Future&lt;Map&lt;String, dynamic&gt;&gt; getUserData() async {</span>\n<span class=\"grvsc-line\">        dynamic userRes;</span>\n<span class=\"grvsc-line\">        userRes = await _apiClient.getUserProfileData(widget.accesstoken);</span>\n<span class=\"grvsc-line\">        return userRes;</span>\n<span class=\"grvsc-line\">      }</span>\n<span class=\"grvsc-line\">      @override</span>\n<span class=\"grvsc-line\">      Widget build(BuildContext context) {</span>\n<span class=\"grvsc-line\">        var size = MediaQuery.of(context).size;</span>\n<span class=\"grvsc-line\">        return Scaffold(</span>\n<span class=\"grvsc-line\">          backgroundColor: Colors.white,</span>\n<span class=\"grvsc-line\">          body: SizedBox(</span>\n<span class=\"grvsc-line\">              width: size.width,</span>\n<span class=\"grvsc-line\">              height: size.height,</span>\n<span class=\"grvsc-line\">              child: FutureBuilder&lt;Map&lt;String, dynamic&gt;&gt;(</span>\n<span class=\"grvsc-line\">                future: getUserData(), //&lt;---</span>\n<span class=\"grvsc-line\">                builder: (context, snapshot) {</span>\n<span class=\"grvsc-line\">                  if (snapshot.hasData) {</span>\n<span class=\"grvsc-line\">                    if (snapshot.connectionState == ConnectionState.waiting) {</span>\n<span class=\"grvsc-line\">                      return Container(</span>\n<span class=\"grvsc-line\">                        height: size.height,</span>\n<span class=\"grvsc-line\">                        width: size.width,</span>\n<span class=\"grvsc-line\">                        color: Colors.blueGrey,</span>\n<span class=\"grvsc-line\">                        child: const Center(</span>\n<span class=\"grvsc-line\">                          child: CircularProgressIndicator(),</span>\n<span class=\"grvsc-line\">                        ),</span>\n<span class=\"grvsc-line\">                      );</span>\n<span class=\"grvsc-line\">                    }</span>\n<span class=\"grvsc-line\">                    //get results from snapshot</span>\n<span class=\"grvsc-line\">                    String fullName = snapshot.data![&#39;FullName&#39;];</span>\n<span class=\"grvsc-line\">                    String firstName = snapshot.data![&#39;FirstName&#39;];</span>\n<span class=\"grvsc-line\">                    String lastName = snapshot.data![&#39;LastName&#39;];</span>\n<span class=\"grvsc-line\">                    String birthDate = snapshot.data![&#39;BirthDate&#39;];</span>\n<span class=\"grvsc-line\">                    String email = snapshot.data![&#39;Email&#39;][0][&#39;Value&#39;];</span>\n<span class=\"grvsc-line\">                    String gender = snapshot.data![&#39;Gender&#39;];</span>\n<span class=\"grvsc-line\">                    return Container(</span>\n<span class=\"grvsc-line\">                      width: size.width,</span>\n<span class=\"grvsc-line\">                      height: size.height,</span>\n<span class=\"grvsc-line\">                      color: Colors.blueGrey.shade400,</span>\n<span class=\"grvsc-line\">                      child: SingleChildScrollView(</span>\n<span class=\"grvsc-line\">                        physics: const BouncingScrollPhysics(),</span>\n<span class=\"grvsc-line\">                     //...</span>\n<span class=\"grvsc-line\">                //...</span></code></pre>\n<p>Finally, let's add the logout feature.</p>\n<p>Add an <code>ElevatedButton</code> widget to the <code>HomeScreen</code>.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">     TextButton(</span>\n<span class=\"grvsc-line\">        onPressed: (){},</span>\n<span class=\"grvsc-line\">        style: TextButton.styleFrom(</span>\n<span class=\"grvsc-line\">        backgroundColor: Colors.redAccent.shade700,</span>\n<span class=\"grvsc-line\">        shape: RoundedRectangleBorder(</span>\n<span class=\"grvsc-line\">               borderRadius: BorderRadius.circular(5)),</span>\n<span class=\"grvsc-line\">               padding: const EdgeInsets.symmetric(</span>\n<span class=\"grvsc-line\">                    vertical: 15, horizontal: 25)),</span>\n<span class=\"grvsc-line\">        child: const Text(&#39;Logout&#39;,</span>\n<span class=\"grvsc-line\">          style: TextStyle(color: Colors.white),           ),</span>\n<span class=\"grvsc-line\">        ),</span>\n<span class=\"grvsc-line\">     ),</span></code></pre>\n<p>On pressing the button, you'll call the <code>logout</code> method on the <code>ApiClient</code> class and pass in the <code>access_token</code> value, and then you route the user to the <code>LoginScreen</code>.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"dart\" data-index=\"15\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">     TextButton(</span>\n<span class=\"grvsc-line\">        onPressed: () async {</span>\n<span class=\"grvsc-line\">          await _apiClient.logout(widget.accesstoken);</span>\n<span class=\"grvsc-line\">          Navigator.pushReplacement(</span>\n<span class=\"grvsc-line\">            context, MaterialPageRoute(builder: (context) =&gt; const LoginScreen()));</span>\n<span class=\"grvsc-line\">        },</span>\n<span class=\"grvsc-line\">        style: TextButton.styleFrom(</span>\n<span class=\"grvsc-line\">        backgroundColor: Colors.redAccent.shade700,</span>\n<span class=\"grvsc-line\">        shape: RoundedRectangleBorder(</span>\n<span class=\"grvsc-line\">               borderRadius: BorderRadius.circular(5)),</span>\n<span class=\"grvsc-line\">               padding: const EdgeInsets.symmetric(</span>\n<span class=\"grvsc-line\">                    vertical: 15, horizontal: 25)),</span>\n<span class=\"grvsc-line\">        child: const Text(&#39;Logout&#39;,</span>\n<span class=\"grvsc-line\">             style: TextStyle(color: Colors.white),</span>\n<span class=\"grvsc-line\">          ),</span>\n<span class=\"grvsc-line\">     ),</span></code></pre>\n<p><img src=\"/968d860d94a6f5f996e709e22dcec84a/demo-project.gif\" alt=\"Preview of demo project\"></p>\n<h2 id=\"conclusion\" style=\"position:relative;\"><a href=\"#conclusion\" aria-label=\"conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conclusion</h2>\n<p>LoginRadius provides high-level, secure, and well-documented APIs to ease the implementation of authentication and user identity management. This tutorial has discussed LoginRadius's benefits and how to use the LoginRadius APIs to handle user authentication and registration in a Flutter application.</p>\n<p>The complete <a href=\"https://github.com/LoginRadius/engineering-blog-samples/tree/master/Flutter/Flutter_Auth_Guide\">source code of the demo application is available on GitHub</a>.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n</style>","headings":[{"value":"Introduction","depth":2},{"value":"Prerequisites","depth":2},{"value":"Getting Started with LoginRadius","depth":2},{"value":"What is LoginRadius?","depth":3},{"value":"Why use LoginRadius?","depth":3},{"value":"Setting Up LoginRadius for Your Application","depth":2},{"value":"Integrating LoginRadius API with Your Flutter Application.","depth":2},{"value":"Step 1: Create a New Flutter project","depth":3},{"value":"Step 2: Install Dependencies","depth":3},{"value":"Project Structure","depth":3},{"value":"Step 3: Setting up the API Client Class","depth":3},{"value":"Step 4: Implement User Registration","depth":3},{"value":"Step 5: Implement User Login","depth":3},{"value":"Step 6: Get User Profile Data","depth":3},{"value":"Step 7: Implement User Logout","depth":3},{"value":"Building the UI","depth":3},{"value":"Registration Screen","depth":3},{"value":"Login Screen","depth":3},{"value":"Home Screen","depth":3},{"value":"Conclusion","depth":2}],"fields":{"slug":"/engineering/guest-post/authenticating-flutter-apps/"},"frontmatter":{"metatitle":null,"metadescription":null,"description":"Developing Flutter apps? Learn how to implement user authentication and registration in your Flutter applications quickly with LoginRadius APIs.","title":"Flutter Authentication: Implementing User Signup and Login","canonical":null,"date":"February 17, 2022","updated_date":null,"tags":["Authentication","Flutter","API"],"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.5037593984962405,"src":"/static/52db7c04cea4a2d8a1eab648a60d075d/03979/user-authentication-for-flutter-apps.png","srcSet":"/static/52db7c04cea4a2d8a1eab648a60d075d/f5f11/user-authentication-for-flutter-apps.png 200w,\n/static/52db7c04cea4a2d8a1eab648a60d075d/6d133/user-authentication-for-flutter-apps.png 400w,\n/static/52db7c04cea4a2d8a1eab648a60d075d/03979/user-authentication-for-flutter-apps.png 800w,\n/static/52db7c04cea4a2d8a1eab648a60d075d/aca38/user-authentication-for-flutter-apps.png 1200w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Yusuf Ahmed","github":null,"bio":"He is a Flutter developer and technical writer. He is focused on learning new technologies and making advancements in the world of tech.","avatar":null}}}},"pageContext":{"id":"a2592925-b065-5c8a-9549-069c4851c3e4","fields__slug":"/engineering/guest-post/authenticating-flutter-apps/","__params":{"fields__slug":"engineering"}}},"staticQueryHashes":["1171199041","1384082988","1711371485","1753898100","2100481360","229320306","23180105","528864852"]}