AWS Amplify For Flutter Part 3: Amplify Authentication

AWS Amplify For Flutter Part 3: Amplify Authentication

Continue the journey of implementing AWS Amplify in your Flutter Application

ยท

10 min read

Preface

This article is the third part of the AWS Amplify For Flutter series, that will explore applying Authentication using AWS Amplify in Flutter

Do read the first part to learn all about Amplify and the second part for using Amplify DataStore with Flutter.

Authentication Library

Amplify Auth Cover.png

Amplify Auth is one of the many libraries provided by AWS Amplify. Amplify Auth perfectly integrates with AWS Cognito and provides an authentication interface. Under the hood, Amplify Auth provides all the necessary authorization to all other AWS services like DataStore, Analytics, Lambda functions etc.

Amplify Auth also provides support for social sign-in providers like:

  • Google
  • Facebook
  • Amazon
  • Apple

Getting Started with Amplify Auth

Prerequisites

  • Install Flutter SDK >= 1.20.
  • iOS configured for at least iOS 11.0.
  • Android configured for at least Android API level 21.
  • Install and Configure Amplify CLI (Elaborated in the first article of this series.)

Adding Auth via Amplify CLI

In your project root directory, run the following command to add Amplify auth:

amplify add auth

For the basic email and password authentication, set the following parameters:

? Do you want to use the default authentication and security configuration?
    `Default configuration`
? How do you want users to be able to sign in?
    `Username`
? Do you want to configure advanced settings?
    `No, I am done.`

Once you have successfully added auth locally, you can run amplify push to push those changes to AWS, so that AWS can allocate the necessary resources to your project. In the backend, Amplify CLI will create an AWS Cloudformation template, store that template to your project's S3 bucket and then run that template to allocate AWS Cognito with your given configuration.

Once the amplify push command is completed successfully, you can notice that the amplifyconfiguration.dart file is updated with the authentication section.

If you are not aware of amplifyconfiguration.dart, Read the first part of this series.

Adding Amplify Auth package to your Flutter Project

Add the following dependency to your pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  amplify_auth_cognito: '<1.0.0'

Then, in your configureAmplify() function, initialize AmplifyAuthCognito() and add it to the Amplify.addPlugins([]) list, similar to other services of Amplify.

static configureAmplify() async {
    // Add Pinpoint and Cognito Plugins, or any other plugins you want to use
    AmplifyAPI apiPlugin = AmplifyAPI();
    AmplifyAuthCognito authPlugin = AmplifyAuthCognito();

    Amplify.addPlugins([
      authPlugin,
      apiPlugin,
    ]);

    // Once Plugins are added, configure Amplify
    // Note: Amplify can only be configured once.
    try {
      await Amplify.configure(amplifyconfig);
    } catch (e) {
      print(
          "Tried to reconfigure Amplify; this can occur when your app restarts on Android.");
    }
  }

Features of Amplify Auth

On contrary to first impressions, AWS Amplify Auth is a versatile and robust authentication service. With Amplify Auth you can achieve the following features:

  • Register a user
  • Confirm user attributes like email/phone
  • Sign-in a user
  • User multi-factor authentication
  • Sign-in with Web UI
  • Sign in anonymously
  • Forgot password
  • Change user password
  • Listen to Auth events
  • Sign-out a user

Let's visit each of these features in detail below.

Register a User

Amplify Auth's signUp function requires a username, password, and a valid email id as parameters in order to register a user. (Phone number can be user in place of email, but that needs to be specified at the time of adding Auth to Amplify via CLI). Call the following function to register a user:

void registerUser() {
  try {
    Map<String, String> userAttributes = {
      'email': 'email@domain.com',
      // 'phone_number': '+15559101234',
      // additional attributes as needed
    };
    SignUpResult res = await Amplify.Auth.signUp(
      username: 'myusername',
      password: 'mysupersecurepassword',
      options: CognitoSignUpOptions(
        userAttributes: userAttributes
      )
    );
    setState(() {
      isSignUpComplete = res.isSignUpComplete;
    });
  } on AuthException catch (e) {
    print(e.message);
  }
}

Confirm user attributes like email/phone

Once a user is registered successfully, that user has to be confirmed via One Time Password (OTP) from email, or password. If email is provided as userAttributes then OTP will be received in email or else on phone, if the phone number is provided in userAttributes.

To confirm the email/phone number, ask for OTP from the user, call confirmSignUp and pass username & OTP as shown below:

try {
  SignUpResult res = await Amplify.Auth.confirmSignUp(
    username: 'myusername',
    confirmationCode: '123456'
  );
  setState(() {
    isSignUpComplete = res.isSignUpComplete;
  });
} on AuthException catch (e) {
  print(e.message);
}

Sign a User In

Once the user has successfully registered, it's time to sign in. Implement the UI for asking username/email and password from the user and pass those credentials to the signIn function as shown below:

try {
  SignInResult res = await Amplify.Auth.signIn(
    username: usernameController.text.trim(),
    password: passwordController.text.trim(),
  );
  setState(() {
    isSignedIn = res.isSignedIn;
  });
} on AuthException catch (e) {
  print(e.message);
}

If a user is already signed in, then the signIn function will result in an exception. In order to call signIn again, the user has to be logged out first. In iOS, if the auth session is expired, you can directly call the signIn function, but in Android, you have to call the signOut function anyway.

User multi-factor authentication

With Amplify, multi-factor authentication can easily be added to your app, but multi-factor can only be added when you initialize auth. If you have already initialized Amplify Auth, then you will have to remove with amplify auth remove and do amplify push to remove auth from AWS, then run amplify add auth with the following configuration to add multi-factor auth:

? Do you want to use the default authentication and security configuration? 
    `Manual configuration`
? Select the authentication/authorization services that you want to use: 
    `User Sign-Up, Sign-In, connected with AWS IAM controls (Enables per-user Storage features for images or other content, Analytics, and more)`
? Please provide a friendly name for your resource that will be used to label this category in the project: 
    `<default>`
? Please enter a name for your identity pool. 
    `<default>`
? Allow unauthenticated logins? (Provides scoped down permissions that you can control via AWS IAM) 
    `Yes`
? Do you want to enable 3rd party authentication providers in your identity pool? 
    `No`
? Please provide a name for your user pool: 
    `<default>`
Warning: you will not be able to edit these selections.
? How do you want users to be able to sign in? 
    `Username`
? Do you want to add User Pool Groups? 
    `No`
? Do you want to add an admin queries API? 
    `No`
? Multifactor authentication (MFA) user login options: 
    `ON (Required for all logins, can not be enabled later)`
? For user login, select the MFA types: 
    `SMS Text Message`
? Please specify an SMS authentication message: 
    `Your authentication code is {####}`
? Email based user registration/forgot password: 
    `Enabled (Requires per-user email entry at registration)`
? Please specify an email verification subject: 
    `Your verification code`
? Please specify an email verification message: 
    `Your verification code is {####}`
? Do you want to override the default password policy for this User Pool? 
    `No`
Warning: you will not be able to edit these selections.
? What attributes are required for signing up? 
    `Email, Phone Number (This attribute is not supported by Facebook, Login With Amazon.)`
? Specify the app's refresh token expiration period (in days): 
    `30`
? Do you want to specify the user attributes this app can read and write? 
    `No`
? Do you want to enable any of the following capabilities?
    `NA`
? Do you want to use an OAuth flow? 
    `No`
? Do you want to configure Lambda Triggers for Cognito? 
    `No`

Sign-in with Web UI

If you don't want to implement UI for authentication and want Amplify to handle everything, then you can implement Web UI in your project.

To ass Web UI, run amplify add auth if not added before and then run amplify update auth, and answer the questions as described below.

? Do you want to use the default authentication and security configuration? 
    `Default configuration with Social Provider (Federation)`
? How do you want users to be able to sign in? 
    `Username`
? Do you want to configure advanced settings? 
    `No, I am done.`
? What domain name prefix you want us to create for you? 
    `(default)`
? Enter your redirect signin URI: 
    `myapp://`
? Do you want to add another redirect signin URI 
    `No`
? Enter your redirect signout URI: 
    `myapp://`
? Do you want to add another redirect signout URI 
    `No`
? Select the social providers you want to configure for your user pool: 
    `<hit enter>`

Once finished, run amplify push to publish your change to AWS.

Web UI will display a sign-in UI inside webview in your app. Webview will have sign-in, register, forgot password and other features implemented. Once the user signs in via Web UI, that user will be redirected to your app and authSession will contain information about that user. In order to redirect back to your app, you have to add a redirect URL to your Android and iOS projects. You can follow these steps to add a redirect URL.

To launch Web UI, call the signInWithWebUI function as shown below:

try {
  SignInResult res = await Amplify.Auth.signInWithWebUI(provider:  AuthProvider.google);
} on AuthException catch (e) {
  print(e.message);
}

Sign in Anonymously

Amplify Auth provides an option for anonymous login. Once you have configured Auth for anonymous authentication, the Cognito auth plugin will automatically obtain guest credentials for the device and that credentials will then be used for all other Amplify plugins. Keep in mind that with anonymous authentication, you can call authentication specific methods like signIn, signOut, resetpassword and confirmPassword. However, you can still get a unique Identity ID that is assigned to your device by calling fetchAuthSession.

All add anonymous authentication to your app, run amplify update auth and answer as described below:

amplify update auth
What do you want to do? Walkthrough all the auth configurations
Select the authentication/authorization services that you want to use: [choose whatever you initially selected - default is User Sign-Up, Sign-In, connected with AWS IAM controls]
Allow unauthenticated logins? (Provides scoped down permissions that you can control via AWS IAM)
โฏ Yes
 No
 I want to learn more.

 [proceed through the rest of the steps choosing the values you want - default is usually "No"]

Forgot password

In order to reset the password, you can call resetPassword function with username/email. This will send the OTP to user attribute configure to receive reset code/OTP.

try {
  ResetPasswordResult res = await Amplify.Auth.resetPassword(
    username: "myusername",
  );
  setState(() {
    isPasswordReset = res.isPasswordReset;
  });
} on AuthError catch (e) {
  print(e);
}

The above code will send a reset code to that specific user. In order to confirm that code, you need to call confirmResetPassword with that same code along with the new password for that user as shown below:

try {
  await Amplify.Auth.confirmPassword(
    username: "myusername",
    newPassword: "mynewpassword",
    confirmationCode: "123456"
  );
} on AuthError catch (e) {
  print(e);
}

Change user password

In order to change the password, make sure a user is logged in, and after that call updatePassword with the old password and new password.

try {
  await Amplify.Auth.updatePassword(
    newPassword: "mynewpassword",
    oldPassword: "myoldpassword"
  );
} on AuthError catch (e) {
  print(e);
}

Listen to Auth events

Amplify Auth plugin provides a way to listen to changes in events through Amplify Hub as shown below:

StreamSubscription hubSubscription = Amplify.Hub.listen([HubChannel.Auth], (hubEvent) {
  switch(hubEvent.eventName) {
    case "SIGNED_IN": {
      print("USER IS SIGNED IN");
    }
    break;
    case "SIGNED_OUT": {
      print("USER IS SIGNED OUT");
    }
    break;
    case "SESSION_EXPIRED": {
      print("USER IS SIGNED IN");
    }
    break;
  }
});

Sign a user out

In order to sign out a user, you need to call the signOut function. Calling signOut without any options will just delete the local cache. To remove logged-in users with the same credentials on another device, you need to pass globalSignOut=true.

try {
  Amplify.Auth.signOut()
} on AuthException catch (e) {
  print(e.message);
}

If the user is logged in via the web UI sign-in method, then globalSignOut will not work.

That's all for AWS Amplify Auth. If you need a detailed example, you can refer to this GitHub repo.

Thank you so much for reading ๐Ÿ˜. If you like this article, then please leave a ๐Ÿ‘ and come say hi on Twitter.

ย