Flutter apps With AWS Amplify Backend: Part 2 — Authentication
Tags: flutter, amplify, aws, android
Published: 2020-09-10 00:20:58


# Flutter apps With AWS Amplify Backend: Part 2 — Authentication

Setting up authentication in a Flutter application is easy with the help of AWS Cognito, now available through Amplify Flutter. If you haven’t check out Part 1 of this series, I suggest you do that first.


## What are we making?

We will be making a simple registration and login system for a Flutter application that uses[ AWS Cognito](https://aws.amazon.com/cognito/) as the authentication backend.

![The login is very low latency](https://cdn-images-1.medium.com/max/2000/1*5TfNM0cj8UmyjIDQmmpq2A.gif)*The login is very low latency*

As always, you can find the code for this tutorial at our Github [repo](https://github.com/Vennify-Inc/flutter-amplify-tutorial/tree/558ac9b31fdcdcdc360a7742c7aabbe11b466642).

### What do we need?

The only thing you need for this tutorial is the app you created in Part 1 of this tutorial series, which is just a sample app with *amplify *initialized.

If you don’t want to read part 1 and you are already familiar with Amplify Flutter, then simply create a new Flutter application and [connect it to a cloud instance of Amplify.](https://docs.amplify.aws/start/getting-started/setup/q/integration/flutter)

## Let’s Get Started

### Create a Basic Amplify Project

If you are using the app you created in Part 1, you can skip this step.

Otherwise, create a new flutter project, and from the project directory run:

    amplify init

### Add AWS Cognito to our Project

From the integrated terminal, run

    amplify add auth

This adds AWS Cognito* *to your project. After following the setup wizard, your terminal should look something like this:

![](https://cdn-images-1.medium.com/max/2142/1*VMaGkKvT76akDVydFKnwaA.png)

Note that we are going to be using emails as the authentication method. I will cover the other methods in future tutorials.

Next, follow the instructions given in the terminal and run *amplify push* to deploy authentication to your cloud project.y

### Checking on the Status of our Resources

You can check the status of your cloud resources by running *amplify status*.

![](https://cdn-images-1.medium.com/max/2000/1*yDIF31ikmnH1ij0Lbf8p7Q.png)

At this point, a user pool should have been created in the cloud for your AWS Cognito service. Go to your [user pools](https://console.aws.amazon.com/cognito/users/?region=us-east-1#/?_k=fqd0vz) (make sure you select your region) and you should see a new user pool.

![](https://cdn-images-1.medium.com/max/3818/1*5WeWr0kHDUu6bdYUqiMOBg.png)

### Interacting with Cloud Resources

A few steps are needed to interact with the cloud, if you just want the final result and don’t care about the step-by-step, go [here ](https://github.com/Vennify-Inc/flutter-amplify-tutorial/tree/558ac9b31fdcdcdc360a7742c7aabbe11b466642)for a checkpoint commit.

Many of these code snippets are derived from the AWS [documentation](https://docs.amplify.aws/lib/auth/signin/q/platform/flutter). I will give explanations about what each logical component does, and provide you with a working example of a login form.

1. **Add packages to pubspec.yaml**

This gives us access to the dart packages for amplify.

    amplify_core: '<1.0.0'
    amplify_auth_cognito: '<1.0.0'

2. **Amplify Initialization**

This code snippet initializes our authentication plugin (and any other plugins we may have) and sets our apps flags so that we can handle an unsuccessful cloud connection in our app.

```dart
void _configureAmplify() async {
  if (!mounted) return;

  // add all of the plugins we are currently using
  // in our case... just one - Auth
  AmplifyAuthCognito authPlugin = AmplifyAuthCognito();
  amplifyInstance.addPlugin(authPlugins: [authPlugin]);

  await amplifyInstance.configure(amplifyconfig);
  try {
    setState(() {
      _amplifyConfigured = true;
    });
  } catch (e) {
    print(e);
  }
}
```

**3. Register a User**

Registering a user makes use of text controllers (not shown here). Once again, state flags (*isSignUpComplete* in this case) are set based on the result of the *SignUp* operation.

```dart
  Future<String> _registerUser(LoginData data) async
  {
    try {
      Map<String, dynamic> userAttributes = {
        "email": emailController.text,
      };
      SignUpResult res = await Amplify.Auth.signUp(
          username: data.name,
          password: data.password,
          options: CognitoSignUpOptions(
              userAttributes: userAttributes
          )
      );
      setState(() {
        isSignUpComplete = res.isSignUpComplete;
        print("Sign up: " + (isSignUpComplete ? "Complete" : "Not Complete"));
      });
    } on AuthError catch (e) {
      print(e);
      return "Register Error: " + e.toString();
    }
  }
```

**4. Sign In a User**

```dart
  Future<String> _signIn(LoginData data) async {
    try {
      SignInResult res = await Amplify.Auth.signIn(
        username: data.name,
        password: data.password,
      );
      setState(() {
        isSignedIn = res.isSignedIn;
      });

      if (isSignedIn)
        Alert(context: context, type: AlertType.success, title: "Login Success").show();

    } on AuthError catch (e) {
      print(e);
      Alert(context: context, type: AlertType.error, title: "Login Failed").show();
      return 'Log In Error: ' + e.toString();
    }
  }
```
And that’s it! Those are all of the logical building blocks that we will use to create a nice signup and login interface. The only thing left to do is integrate these components into a user interface, which we will do next.

### Flutter Login

For convenience, we will use a flutter package called [flutter_login](https://pub.dev/packages/flutter_login) to make our first integration quick and painless. As with all things in life, KISS.

![](https://cdn-images-1.medium.com/max/3840/0*M4etO1FILPrw9kUT.jpg)

### Main.dart

```dart
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_core/amplify_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_login/flutter_login.dart';

import 'amplifyconfiguration.dart';

void main() {
  runApp(MaterialApp(
    home: MyApp(),
  ));
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  // gives our app awareness about whether we are succesfully connected to the cloud
  bool _amplifyConfigured = false;

  // Instantiate Amplify
  Amplify amplifyInstance = Amplify();

  // controllers for text input
  final emailController = TextEditingController();
  final passwordController = TextEditingController();

  bool isSignUpComplete = false;
  bool isSignedIn = false;

  @override
  void initState() {
    super.initState();

    // amplify is configured on startup
    _configureAmplify();
  }

  @override
  void dispose() {
    // Clean up the controller when the widget is removed from the
    // widget tree.
    emailController.dispose();
    passwordController.dispose();

    super.dispose();
  }

  void _configureAmplify() async {
    if (!mounted) return;

    // add all of the plugins we are currently using
    // in our case... just one - Auth
    AmplifyAuthCognito authPlugin = AmplifyAuthCognito();
    amplifyInstance.addPlugin(authPlugins: [authPlugin]);

    await amplifyInstance.configure(amplifyconfig);
    try {
      setState(() {
        _amplifyConfigured = true;
      });
    } catch (e) {
      print(e);
    }
  }

  Future<String> _registerUser(LoginData data) async
  {
    try {
      Map<String, dynamic> userAttributes = {
        "email": emailController.text,
      };
      SignUpResult res = await Amplify.Auth.signUp(
          username: data.name,
          password: data.password,
          options: CognitoSignUpOptions(
              userAttributes: userAttributes
          )
      );
      setState(() {
        isSignUpComplete = res.isSignUpComplete;
        print("Sign up: " + (isSignUpComplete ? "Complete" : "Not Complete"));
      });
    } on AuthError catch (e) {
      print(e);
      return "Register Error: " + e.toString();
    }
  }

  Future<String> _signIn(LoginData data) async {
    try {
      SignInResult res = await Amplify.Auth.signIn(
        username: data.name,
        password: data.password,
      );
      setState(() {
        isSignedIn = res.isSignedIn;
      });
    } on AuthError catch (e) {
      print(e);
      return 'Log In Error: ' + e.toString();
    }
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: FlutterLogin(
          logo: 'assets/vennify_media.png',
          onLogin: _signIn,
          onSignup: _registerUser,
          onRecoverPassword: (_) => null,
          title:'Flutter Amplify'
      ),
    );
  }
}
```

Of course, add the following lines to your **pubspec.yaml **to enable our new packages:

    flutter_login: '<1.0.0'
    rflutter_alert: '^1.0.3'

![You will need to add your own image to assets for the flutter_login logo](https://cdn-images-1.medium.com/max/2000/1*jrj-yWFUhp7-XvEh8D6YrQ.png)*You will need to add your own image to assets for the flutter_login logo*

### Testing User Registration

To register a new user, simply use the intuitive flutter_login interface to submit a new user request to Amplify Cognito.

![Use a fake email, or a real one..your choice.](https://cdn-images-1.medium.com/max/2000/1*nzobJpwzdemmHBhP73qexg.png)*Use a fake email, or a real one..your choice.*

Navigate to your [user pool](https://console.aws.amazon.com/cognito/users/?region=us-east-1#/pool/) and you should see a new user that was created:

![In this case, I created two users](https://cdn-images-1.medium.com/max/2814/1*y5oMiS8VVhfZD_eK3M2Rnw.png)*In this case, I created two users*

Select one of the users in your pool. Notice that the status is ‘UNCONFIRMED’. In this tutorial, we will be confirming our users manually simply by tapping on the ‘Confirm User’ button. In a future tutorial, I will demonstrate how to confirm users automatically using a verification code sent to their phone or email.

![Tap ‘Confirm User’ to activate the new account](https://cdn-images-1.medium.com/max/2450/1*EQ__KgaTm5TmmNckIV5Eiw.png)*Tap ‘Confirm User’ to activate the new account*

### Testing User Login

Let’s try to login using the user that we just created.

![Login and login success](https://cdn-images-1.medium.com/max/2132/1*MI_3agTLE2AF21Ci9BBnFw.png)*Login and login success*

![This gif is mandatory](https://cdn-images-1.medium.com/max/2000/0*Np2VC-V5YLhI6OwU)*This gif is mandatory*

### Wrapping Up

Still with me? At this point, we have a very basic authentication system for our app that leverages AWS Cognito. There are still several other topics to explore in regards to authentication, but they are beyond the scope of this tutorial. Some other challenges we need to tackle include:

1. Authentication based on different credential types

1. Automatic confirmation of users

1. 2FA and custom authentication processes

I hope to cover these topics in detail in a future article. Until then, let’s continue on our journey of nailing down the basics of AWS Amplify with Flutter. Next up — [analytics](https://docs.amplify.aws/lib/analytics/getting-started/q/platform/flutter).

### This Series

**Part 1:** [Basic Setup](https://medium.com/@vennify.education/flutter-apps-with-aws-backend-part-1-basic-setup-7e1dd53e9161)

**Part 2:** [Authentication](https://medium.com/@vennify.education/flutter-apps-with-aws-backend-part-2-authentication-a66136f23995)

**Part 3:** [Analytics](https://medium.com/@vennify.education/flutter-apps-with-aws-backend-part-3-analytics-bdb8b5bad5c0)

**Part 4:** [Storage](https://medium.com/@vennify.education/flutter-apps-with-aws-backend-part-4-storage-74ae2dbdc4b5)