Creating Flutter app with AWS serverless backend — Part 1: Social login

Ilya Bershadskyi
OmiSoft
Published in
6 min readMar 16, 2021
Flutter + AWS Amplify + Cognito

For this app, I am going to use AWS Cognito to manage user login and authentication. In this scenario, my app needs to communicate with Cognito directly to obtain an authentication token and after that, I will add this token to every request send to my backend.

First, you need to create your Flutter app. I assume you already know how to do this but in case something is not clear here is a guide https://flutter.dev/docs/get-started/codelab

Then you configure Cognito and create proper user pools there. Configuring Cognito can be done manually but it is advised to use amplify command line tool. It gives you a guided editor to setup everything you will need for this project. Please also keep in mind that when you setup Cognito auth with Amplify except user and identity pools it also creates Lambda handlers needed to handle authentication events, in case if you decide to setup Cognito manually you will have to create those handlers yourself.

Here is an official amplify guide — https://docs.amplify.aws/cli/start/install

So first you need to install amplify.

> npm install -g @aws-amplify/cli

Now you need to add amplify_flutter libraries to your flutter project. Insert this into pubspec.yaml:

amplify_flutter: '<1.0.0'
amplify_auth_cognito: '<1.0.0'
amplify_analytics_pinpoint: '<1.0.0'

Now you need to generate amplifyconfiguration.dart which will contain all relevant AWS configurations. Amplify CLI will do this for you. After this is done navigate to your flutter application folder.

First, you run:

> amplify init

Here you will need to enter basic settings for your project including project name, environment name, etc. The most important part here is the authentication method you want to use. I personally used AWS access keys but you can also sign-in into your AWS profile instead. Also at this stage, you need to choose AWS region where you want to deploy your stuff. If you don’t care you can select anyone.

Now, your amplify project is initialized and you can proceed adding services.

In my case amplify_flutter by default required analytics to be enabled in order to work so I add that first:

> amplify add analytics

Also, I enabled sending analytic events for unauthorized users just in case I need them in the future.

Adding analytics step may be not needed for you. I believe this is a bug in amplify_flutter which will be fixed at some point.

Now it is time to add Auth. You will need your Google & Facebook app OAuth credentials in this step so create it if you don’t have it yet. You can find some info on how to do it here:

Important note 1: amplify_flutter handles social network logins using web ui and not native SDKs so you need to setup you social identity providers as OAuth login in Cognito. In Google and Facebook app setting you need to create access keys and enter data for Web(OAuth) clients and not iOS/Android apps.

Important note 2: During this process you will be asked to enter login/logout redirect URLs. This URLs will be used to make the device pass control back to your app after user finishes login action on web. In order for your app to handle it properly these URLs should have your custom scheme. My suggestion is to define them like <your_app_name>://login/ and <your_app_name>://logout/

When you are done with preparations run the command to add Auth to your project

> amplify add auth

This will guide you through Congnito user pool setup. At this stage I only care about login via social networks(namely Google and Facebook) but later I am also going to add login with phone number and OTP. So I allowed users to use phone number for login as well.

After this basic AWS services setup is finished. You can run

> amplify push

to deploy it to the cloud.

Checkpoint

Now you can check that amplify created everything you need. Go to your AWS management console and check the following things:

  1. Go to Cognito -> Federeated Identities. Check that identity pool is created
Identity pools

2. Go to Cognito -> User Pools. Check that user pool is created.

User pools

Also If you go to your user pool -> Federation -> Identity providers you should find Facebook and Google enabled there.

Identity providers for our user pool

If this is in order then you are good to go.

Flutter app configuration

Here is the official guide from AWS: https://docs.amplify.aws/lib/auth/signin/q/platform/flutter

In my app, I am using Social sign in with web UI part.

You need to add activity to your Android.manifest

<activity       android:name="com.amazonaws.mobileconnectors.cognitoauth.activities.CustomTabsRedirectActivity">    
<intent-filter>

<action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="<your_app_name>" />

</intent-filter>
</activity>

Please note that your_app_name here is your custom url scheme that you defined when created login/logout redirect urls

For ios you need to add this section to Info.plist:

<! — ADD AN ENTRY TO CFBundleURLTypes for Cognito Auth 
<! — IF YOU DO NOT HAVE CFBundleURLTypes, YOU CAN COPY THE WHOLE BLOCK BELOW
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>your_app_name</string>
</array>
</dict>
</array>

Now you can initialize Amplify in you main.dart:

void main() async {
Fimber.plantTree(DebugTree(useColors: true));

WidgetsFlutterBinding.ensureInitialized();
_initAmplifyFlutter();

SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitDown, DeviceOrientation.portraitUp]).then((_) {
runApp(
MyApp(
home: RegisterScreen(),
),
);
});
}

void _initAmplifyFlutter() async {
AmplifyAuthCognito auth = AmplifyAuthCognito();
Amplify.addPlugins([auth]);

// Initialize AmplifyFlutter
try {
await Amplify.configure(amplifyconfig);
} on AmplifyAlreadyConfiguredException {
Fimber.d(
"Amplify was already configured. Looks like app restarted on android.");
}
}

After Amplify is configured you can finally login the user!

Future<bool> login() async {
try {
SignInResult res = await Amplify.Auth.signInWithWebUI(provider: AuthProvider.facebook);
Fimber.d("SigningResult: ${res.isSignedIn}");

if (res.isSignedIn) {
var atributes = (await Amplify.Auth.fetchUserAttributes()).toList();
for (var attribute in atributes) {
Fimber.d("Attribute: ${attribute.value}");
}
CognitoAuthSession res =
await Amplify.Auth.fetchAuthSession(options: CognitoSessionOptions(getAWSCredentials: true));
Fimber.d("TOKEN length: ${res.userPoolTokens.accessToken.length}");
Fimber.d("START OF TOKEN: ${res.userPoolTokens.accessToken}");
Fimber.d(
"END OF TOKEN: ${res.userPoolTokens.accessToken.substring(res.userPoolTokens.accessToken.length - 100)}");
authToken = res.userPoolTokens.accessToken;
return true;
} else {
return false;
}
} on AuthException catch (e) {
Fimber.e('SignIn exception', ex: e);
return false;
}
}

Side note: if you want to print Cognito token to console to use it in your favorite REST client keep in mind that it is very long. Token has more symbols than Flutter allow you to print in one print call. This is why I print it in two parts:

Fimber.d("START OF TOKEN: ${res.userPoolTokens.accessToken}");
Fimber.d("END OF TOKEN: ${res.userPoolTokens.accessToken.substring(res.userPoolTokens.accessToken.length - 100)}");

to use it in your REST client you will need to concatenate those parts yourself. Keep in mind there is a few characters overlap added to ensure no characters have been missed.

And here it is: after login button click you should see facebook login page similar to this one:

After successful login user should be redirected back to the app and you will be able to fetch token as shown above.

In the next part, I am going to tell about adding login with phone + one-time password(or SMS code). Stay tuned.

Tap the 👏 button if you found this article useful!

Need a Flutter mobile app with clean & maintainable code? Click here to get an estimate! Or find us on Facebook and Twitter.

--

--