The big interest in my previous post “How to use Firebase Auth with Alexa Account Linking” caused me to create this more in-depth tutorial.
My project structure is as follows:
- Android/iOS App developed with Flutter
- Database and user management on Firebase
- Alexa Skill hosted on AWS Lambda ARN
I chose this mix of technology to share one code base for the mobile apps. Furthermore, Google provides high quality packages to implement Firebase support into the apps. The packages firebase_auth and flutter_firebase_ui cover login, registration and all things this entails like forgotten passwords. It’s also relatively future-proof considering Google’s new OS Fuchsia and Flutter likely becoming the standard to develop for this platform.
When you have set up your Alexa Skill go to the “build” tab in the the developer console and choose “Account linking”. Enable the option to “allow users to create an account or link to an existing account with you.”
For the security provider information choose “Auth Code Grant”. We will come to the Authorization URI and Access Token URI in the next section. Choose your Client ID and Secret according to your project. For this tutorial I used credentials in request body as the Authentication Scheme, but for a real-world project you should amend the code to use HTTP Basic. Scope is “an optional list of permissions for the other service. If your resource server supports different scopes for access, enter those here. You can provide up to 15 scopes.” The Domain List is “an optional list of domains that the authorization URI can retrieve data from. If your login page retrieves content from other domains, enter those in this list.” Further details on all the options can be found in the Alexa Documentation.
Since I have not found any option to use Firebase as an OAuth 2.0 provider I built a simplified version of it myself. I created a login page with Firebase UI for Web and hosted it on Firebase Hosting. In the Firebase Console you will see the domain to your project website. It should be something like
https://<projectname>.firebaseapp.com. This is your Authorization URI.
This page is shown when your user links his account with your service. When the user logged in successfully it will create an authentication code, store it in a Firestore collection called auth_codes and send it back to Amazon by redirecting the browser to the redirect_uri.
Amazon then uses this auth_code to retrieve a token pair from the authentication function. For this I used Firebase functions. After deploying your functions you will see an URL in the Firebase Console. It should look something like
https://us-central1-<projectname>.cloudfunctions.net/access_token. This is your Access Token URI.
This time I also included the function to retrieve a new authentication_token with the refresh_token. This is implemented in a very primitive and naive way. In a real-world application you should, among other things, first check the user’s identity with the user id provided by Amazon. Furthermore, there might be clashes with two or more users having the same refresh_token.
Now comes the most important part. This took me hours of googling.
Please mind the
firebase.auth().signOut(); at line 55. Without this, the AWS Lambda will not finish and thus you’ll get an error like
Task timed out after 8.01 seconds .