Flutter and AWS (as of March 2019)

update 5/2/2020:

Bernd Wessels
5 min readMar 5, 2019

The amazon_cognito_cognito_identity_dart seems not to be supported anymore, BUT I’ve been contacted by Oleksii that he is actively maintaining a new version https://pub.dev/packages/amazon_cognito_identity_dart_2

tldr;

Your Flutter app can now login with Federated Identity Providers like Google or Facebook using AWS Cognito to access AWS Services securely with sophisticated fine grain access control.

While Flutter has strong Firebase support, it is still a bit too new for official support from AWS.

Fortunately there is already a flutter plugin that enables Flutter Apps to access AWS Services using Sigv4 Request Signing and Cognito Identities support.

What do you get?

  • Flutter (1.2)
  • Android
  • IOS
  • Cognito User Pools Sign In (email + mfa)
  • Cognito Identity Pools (federated identities)
  • Facebook Sign In
  • Google Sign In

What can you do with it?

  • User and identity management with AWS Cognito
  • Secured access to AWS Services like API Gateway, AppSync, …
  • Sophisticated fine grain access management via Cognito Identities

This is how I got it to work on Android and IOS:

Flutter

I’ve upgraded to the latest (as of March 2019) version of flutter which is v1.2.1 .

I am on the beta channel, since it moves a bit faster than the stable channeland is a bit more reliable than the dev channel.

I also keep my Android Studio and Flutter plugins up to date.

Run flutter doctorto make sure everything is as expected:

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel beta, v1.2.1, on Microsoft Windows [Version 10.0.17134.590], locale en-NZ)
[√] Android toolchain — develop for Android devices (Android SDK version 28.0.3)
[√] Android Studio (version 3.3)
[√] IntelliJ IDEA Community Edition (version 2017.3)

Add the following dependencies to the pubspec.yml file:

amazon_cognito_identity_dart:
git:
url: git://github.com/BerndWessels/amazon-cognito-identity-dart.git

google_sign_in: 4.0.1+1

flutter_facebook_login: ^1.2.0

Once all outstanding pull requests have been merged you can use the original dependency:

amazon_cognito_identity_dart: ^0.0.22

google_sign_in: 4.0.1+1

flutter_facebook_login: ^1.2.0

I wrote a very simple flutter app to showcase the usage of Google and Facebook as Cognito Federated Identity Providers :

For this to work you also need a secret.dart file that looks like this:

final String cognitoIdentityPoolId = 'ap-southeast-2:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
final String cognitoUserPoolId = 'ap-southeast-2_xxxxxxxxx';
final String cognitoClientId = 'xxxxxxxxxxxxxxxxxxxxxxxxxx';
final String apiEndpointUrl = 'https://xxxxxxxxxx.execute-api.ap-southeast-2.amazonaws.com/default';

There are definitely better ways to store your secrets, but as a takeaway just remember to separate these values out and DO NOT check them in to public repositories!

Google Sign In

To sign in with Google I use the google_sign_in package.

We need to create a file called google-services.json for Android and GoogleServices-Info.plist for IOS. Unfortunately the only way I could find to create these files is to use Firebase. So basically you have to create a (free) Firebase Projectand create the Android and IOS apps in there.

For Android:

  • Click Add app
  • Choose Android
  • Enter the package nameand signing certificate SHA-1
  • Register the app
  • Now you can download the google-services.jsonfile and copy it into your flutter apps android/app/ folder.
  • You need to add apply plugin: 'com.google.gms.google-services' to your android/app/build.gradle file.
  • You also need to add classpath 'com.google.gms:google-services:4.2.0' to your android/build.gradle file.

For IOS:

  • Click Add app
  • Choose IOS
  • Enter the IOS Bundle ID
  • Register the app
  • Open Xcode. You’ll have to paste this into Xcode to properly register GoogleServices-Info.plist.
  • Select GoogleServices-Info.plist from the file manager and drag that file into the Runner directory, [my_project]/ios/Runner/GoogleServices-Info.plist.
  • A dialog will show up and ask you to select the targets, select the Runner target.
  • Then add the CFBundleURLTypes attributes below into the ios/Runner/Info.plist file.
<!-- Put me in the [my_project]/ios/Runner/Info.plist file -->
<!-- Google Sign-in Section -->
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<!-- TODO Replace this value: -->
<!-- Copied from GoogleServices-Info.plist key REVERSED_CLIENT_ID -->
<string>com.googleusercontent.apps.000000000000-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</string>
</array>
</dict>
</array>
<!-- End of the Google Sign-in Section -->

Facebook Sign In

To sign in with Facebook I use the flutter_facebook_login package.

First register a new Facebook app by following these instructions. This will give you all the values you need for the next steps.

For Android:

Copy-paste the following to your strings resource file. If you don’t have one, just create it.

/android/app/src/main/res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">Your App Name here.</string>
<!-- Replace "000000000000" with your Facebook App ID here. -->
<string name="facebook_app_id">000000000000</string>
<!--
Replace "000000000000" with your Facebook App ID here.
**NOTE**: The scheme needs to start with `fb` and then your ID.
-->

<string name="fb_login_protocol_scheme">fb000000000000</string>
</resources>

Copy-paste the following to your Android Manifest:

/android/app/src/main/AndroidManifest.xml

<meta-data android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id"/>
<activity android:name="com.facebook.FacebookActivity"
android:configChanges=
"keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="@string/app_name" />
<activity
android:name="com.facebook.CustomTabActivity"
android:exported="true">
<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="@string/fb_login_protocol_scheme" />
</intent-filter>
</activity>

For IOS:

Copy-paste the following to your Info.plist file, before the ending </dict></plist> tags.

/ios/Runner/Info.plist

<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<!--
Replace "000000000000" with your Facebook App ID here.
**NOTE**: The scheme needs to start with `fb` and then your ID.
-->

<string>fb000000000000</string>
</array>
</dict>
</array>
<key>FacebookAppID</key><!-- Replace "000000000000" with your Facebook App ID here. -->
<string>000000000000</string>
<key>FacebookDisplayName</key>
<!-- Replace "YOUR_APP_NAME" with your Facebook App name. -->
<string>YOUR_APP_NAME</string>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>fbapi</string>
<string>fb-messenger-share-api</string>
<string>fbauth2</string>
<string>fbshareextension</string>
</array>

AWS Cognito

Finally we have to setup Cognito to accept Google and Facebook as identity providers.

  • Create a new Cognito User Pool
  • Create a new App Client in the new Cognito User Pool
  • Create a new Cognito Identity Pool
  • On the Authentication Providers Cognito tab enter the User Pool ID and the App client id
  • On the Authentication Providers Facebook tab enter the Facebook AppID
  • On the Authentication Providers OpenID tab check the accounts.google.com box
  • In the AWS IAM console go to Identity Providers and edit the accounts.google.com OpenID Connect Provider.
  • For Google you have 2 different OAuth Client IDs. One is for Android and can be found under{client: {oauth_client: {client_id: xxx}}} in your android/app/google-services.json . The other one is for IOS and can be found in yourios/Runner/GoogleServices-Info.plist .
  • Add these two Google Client IDs to the accounts.google.com Audiences in this format xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com

This should be it. Now users logging in with Google or Facebook will be stored in the Cognito Federated Identity Pool.

API

To test that everything works just create a new Lambda and an API Gateway Trigger and protect the API with AWS_IAM.

Your flutter app can now call this protected endpoint and within the Lambda you can even get the Cognito Identity of the calling user.

This will also work for AppSync if you prefer GraphQL endpoints and allows for very sophisticated fine grain access management using the Cognito Identity within the AppSync Resolver Functions.

Security Reminder

If you check in your app to a public repository make sure you DO NOT check in any sensitive data.

Basically exclude:

  • secret.dart
  • google-services.json
  • GoogleServices-Info.plist
  • Info.plist

--

--