Flutter and AWS (as of March 2019)
update 5/2/2020:
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 channel
and is a bit more reliable than the dev channel
.
I also keep my Android Studio and Flutter plugins up to date.
Run flutter doctor
to 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 Project
and create the Android and IOS apps in there.
- Create a (free) Firebase Project
- Open the
Project Settings
For Android:
- Click
Add app
- Choose Android
- Enter the
package name
andsigning certificate SHA-1
- Register the app
- Now you can download the
google-services.json
file and copy it into your flutter appsandroid/app/
folder. - You need to add
apply plugin: 'com.google.gms.google-services'
to yourandroid/app/build.gradle
file. - You also need to add
classpath 'com.google.gms:google-services:4.2.0'
to yourandroid/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 theRunner
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 theios/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 yourandroid/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