- Apple Sign In with Flutter & Firebase Authentication
- Some context
- Prerequisites
- Project Setup
- Checking if Apple Sign In is available
- Adding the UI code
- Adding the authentication code
- Using the authentication code
- Testing things
- Dive into Firebase Auth on Flutter: Phone and Anonymous Authentication
- Dive into Firebase Auth on Flutter: Email and Link Sign-in
- Flutter is an awesome tool for developing apps on multiple platforms from one codebase. While Flutter is useful, it…
- Dive into Firebase Auth on Flutter: Third-Party Authentication
- Using FlutterFire to authenticate Firebase users with third-party identity providers.
- Setup
- Phone Authentication
- Sending the SMS
- Signing in
- Anonymous Authentication
- Non-Permanence
- Conclusion
Apple Sign In with Flutter & Firebase Authentication
Updated Sep 20, 2021
In this tutorial we’ll see how to add Apple Sign In to our Flutter & Firebase apps from scratch.
We will use the the_apple_sign_in Flutter plugin available on pub.dev.
This plugin makes it possible to support Apple Sign In on iOS, and enable it as an authentication method on Firebase.
However, note that this plugin supports iOS only, not Android, and you can only use this on devices running iOS 13 and above.
If you want to enable Apple Sign In on both iOS and Android, you should use sign_in_with_apple instead. This will work on both platforms, but the integration will require some server-side code.
Subscription Management for Flutter apps. RevenueCat gives you everything you need to build, analyze, and grow IAPs with just a few lines of code.
Some context
Apple Sign In is a new authentication method that is available on iOS 13 and above.
It is very convenient, as your iOS users already have an Apple ID, and can use it to sign in with your app.
So just as you would offer Google Sign In on Android, it makes sense to offer Apple Sign In on iOS.
Prerequisites
- Xcode 11 installed
- An Apple Developer Account
- An iOS 13.x device or simulator, signed in with an Apple ID
Project Setup
After creating a new Flutter project, add the following dependencies to your pubspec.yaml file:
Note: we will use Provider for dependency injection, but you can use something else if you prefer.
Next, we need add Firebase to our Flutter app. Follow this guide for how to do this:
After we have followed the required steps, the GoogleService-Info.plist file should be added to our Xcode project.
And while in Xcode 11, select the Signing & Capabilities tab, and add «Sign In With Apple» as a new Capability:
Adding Sign In With Apple capability
Once this is done, ensure to select a team on the Code Signing section:
Set Code Signing options
This will generate and configure an App ID in the «Certificates, Identifiers & Profiles» section of the Apple Developer portal. If you don’t do this, sign-in won’t work.
As a last step, we need to enable Apple Sign In in Firebase. This can be done under Authentication -> Sign-in method :
This completes the setup for Apple Sign In, and we can dive into the code.
Checking if Apple Sign In is available
Before we add the UI code, let’s write a simple class to check if Apple Sign In is available (remember, we’re supporting iOS 13+ only):
Then, in our main.dart file, let’s modify the entry point:
The first line prevents an exception that occurs if we attempt to send messages across the platform channels before the binding is initialized. This is needed because we’re calling Firebase.initializeApp() before running the app.
Then, we check if Apple Sign In is available by using the class we just created.
And we use Provider to make this available as a value to all widgets in our app.
Note: this check is done upfront so that appleSignInAvailable is available synchronously to the entire widget tree. This way we don’t need a FutureBuilder to perform this check in our widgets.
Adding the UI code
Instead of the default counter app, we want to show a Sign In Page with a button:
Note: we use a collection-if to only show the AppleSignInButton if Apple Sign In is available. See this video for UI-as-code operators in Dart.
Back to our main.dart file, we can update our root widget to use the SignInPage :
At this stage, we can run the app on an iOS 13 simulator and get the following:
Apple Sign In Button
Adding the authentication code
Here is the full authentication service that we will use to sign in with Apple (explained below):
First, we pass a List argument to our method. Scopes are the kinds of contact information that can be requested from the user ( email and fullName ).
Then, we make a call to AppleSignIn.performRequests and await for the result.
Finally, we parse the result with a switch statement. The three possible cases are authorized , error and cancelled .
Authorized
If the request was authorized, we create an OAuthProvider credential with the identityToken and authorizationCode we received.
We then pass this to _firebaseAuth.signInWithCredential() , and get a UserCredential that we can use to extract the FirebaseUser .
And if we requested the full name, we can update the profile information of the FirebaseUser object with the fullName from the Apple ID credential.
Note: According to this issue, the Apple sign-in APIs always return null for the fullName data after the initial login. After that, the only information that is returned is the uid . Hence the code above has some defensive null checks before updating the Firebase display name.
Error or Cancelled
If authentication failed or was cancelled by the user, we throw a PlatformException that can be handled by at the calling site.
Using the authentication code
Now that our auth service is ready, we can add it to our app via Provider like so:
Then, in our SignInPage , we can add a method to sign-in and handle any errors:
Finally, we remember to call this on the callback of the AppleSignInButton :
Testing things
Our implementation is complete, and we can run the app.
If we press the sign-in button and an Apple ID is not configured on our simulator or device, we will get the following:
Apple Sign In Settings prompt
After signing in with our Apple ID, we can try again, and we will get this:
After continuing, we are prompted to enter the password for our Apple ID (or use touch ID/face ID if enabled on the device). If we have requested full name and email access, the user will have a chance edit the name, and choose to share or hide the email:
After confirming this, the sign-in is complete and the app is authenticated with Firebase.
Note: if the sign-in screen is not dismissed after authenticating, it’s likely because you forgot to set the team in the code signing options in Xcode.
The next logical step is to move away from the SignInPage and show the home page instead. This can be done by adding a widget above the SignInPage , to decide which page to show depending on the onAuthStateChaged stream of FirebaseAuth . See this tutorial for how to accomplish this.
Congratulations, you have now enabled Apple Sign In in your Flutter app! Your iOS users are grateful. 🙏
The full source code for this tutorial is here on GitHub.
Источник
Dive into Firebase Auth on Flutter: Phone and Anonymous Authentication
Firebase includes a variety of tools to help developers build, grow, and improve their apps. One of the most used of these tools is Firebase Authentication, as it allows developers to restrict who can read or write data to the Firebase backend and provides a secure environment for their user’s data.
This is the third part of a short series covering Firebase Authentication with the FlutterFire plugin. In this article we will learn how to authenticate in Firebase with both Phone Authentication, which uses SMS validation codes, and Anonymous Authentication. In order to completely follow along with the Phone Authentication portion of this article, you will need a physical iOS or Android device that is capable of receiving SMS messages, though you should still be able to get some of the general functionality on an emulator with a test number (we’ll discuss this in a later section). The Firebase Anonymous Authentication feature can be tested on either an iOS simulator or an Android emulator if a physical device is not available.
In the first article of this series we learned how to add Firebase to a Flutter project using FlutterFire, how to register and authenticate a new user in Firebase using an email and password, and how to authenticate a user with an emailed link.
Dive into Firebase Auth on Flutter: Email and Link Sign-in
Flutter is an awesome tool for developing apps on multiple platforms from one codebase. While Flutter is useful, it…
In the second article we learned about third-party identity providers, and how to authenticate in Firebase using GitHub and Google credentials.
Dive into Firebase Auth on Flutter: Third-Party Authentication
Using FlutterFire to authenticate Firebase users with third-party identity providers.
If this is the first article you have come across from this series, I highly recommend at least briefly reading over the setup portion of the first article if you are not familiar with the FireFlutter plugin. If you would like an in-depth understanding of Firebase Authentication on Flutter, then I would suggest reading both of the previous articles in their entirety before starting this one. If you’re only interested in phone or anonymous authentication and have already implemented FireFlutter in your app, then starting in this article should be just fine 🙂
Setup
Before we can get into the code for our app in this article, we’ll need to do a few things to get setup:
- Create a Firebase project
- Create a new Flutter application
- Link the Android portion of our Flutter app to Firebase
- Import our dependencies
- Lay out the code for our starter app
We can find instructions for steps 1–3 in the first article of this series, or in the official documentation for creating a Firebase project and linking a Flutter app, so I won’t repeat them here. One thing worth mentioning here is that we will need to include our signing key’s SHA-1 for our Android app to use Phone Authentication, which is also covered in the first article. After completing those steps we can open up the pubspec.yaml file in our Flutter project and add the three following dependencies under the dependencies heading:
These will bring in the two required plugins for connecting to our Firebase project and using Firebase Authentication, plus a third-party plugin that will allow us to automatically get the phone number for the user’s device without typing it in. After adding those three lines, be sure to sync your app to pull down these dependencies. This can be done in Android Studio by clicking on the Pub get button in the Flutter commands banner.
For the final setup step, let’s go into main.dart and add the following code for our starter app:
There’s a few things to pay attention to in this starting code. First, you’ll notice that we have already initialized Firebase and our Flutter bindings in the main() method. If we go down into our _MyHomePageState class, you’ll see that we’re saving a reference to the app’s scaffolding context via a key. While we’re not using this now, it will be useful later when we add status messages to our application. Finally, we’ve set the resizeToAvoidBottomPadding property in our Scaffold widget to false . This will prevent drawing errors later when the keyboard takes up a portion of our device screen. Now that we’re set up, let’s dig into using Firebase Phone Authentication.
Phone Authentication
Before we start writing our code to use Phone Authentication, let’s first return to our project in the Firebase console. Once there, we’ll need to go into the Authentication page, which can be found under the Develop tab in the left page navigation part, and over to the Sign-in method tab.
From here we’ll need to open the Phone section under Sign-in Providers and click on the Enable toggle. While we’re here, let’s also click on the chevron next to the text Phone numbers for testing (optional). Once that section is opened, we can add a test phone number and verification code that we can use while developing our app without getting blocked by Firebase’s anti-spamming tools. It’s worth noting that we don’t need to use the device’s actual phone number for testing purposes. It’s actually recommended that we don’t add our real numbers to the allowlist, that way we can use them to test the entire flow later. Once all of that is done, let’s go ahead and click on the blue Save button.
Great, now that we’re set up in the Firebase console, let’s get back to our code. We can start by adding the rest of our class-level fields to the top of _MyHomePageState.
This code gets a reference to the FirebaseAuth instance, creates a pair of TextEditingController objects for keeping track of anything entered by the user in two TextFormField widgets that we will create later, stores a verification ID that we will get through Firebase Phone Authentication, and creates a new object, _autoFill , that we will use for retrieving the physical device’s phone number. The _scaffoldKey object should have already existed in our initial app code, and will be used for displaying status messages in our app.
Next we will need to flesh out our build() method, but let’s do this in stages. First we’ll add a new TextFormField into the widget array in the middle of build() . This will add a new area where users can type in their own phone number.
Following that TextFormField will be a Container widget that wraps a RaisedButton . This RaisedButton will use the autofill plugin that we added to our project earlier to request the user’s physical device’s phone number and populate it into our TextFormField . You’ll notice that this is also an async operation, so the action won’t block our app while retrieving the device’s information.
Back in our build() method we can add an additional Container widget to the array that will wrap another RaisedButton .
This button will take the phone number collected from the user and submit it to Firebase to request a verification code through SMS. Let’s go ahead and just stub out the verifyPhoneNumber() method for now, then we’ll come back to it after we’ve finished our build() method.
To wrap up our build() method, let’s add one more TextFormField and Container / RaisedButton combo to get a field that accepts our SMS verification code and submits it to Firebase.
We can also stub out the signInWithPhoneNumber() method for now.
Once that’s done, our build() method should look like this:
and if we run our app now, the UI should look like this:
Sending the SMS
Now we can get started on the more complex portions of Phone Authentication. Let’s start off by going back into our stubbed out verifyPhoneNumber() method. We will first need to create a series of callbacks that will be used by Firebase to handle the Phone Authentication process. Our first callback will check to see if the user has previously authenticated, and if they can be automatically signed in to Firebase without submitting another SMS verification code:
You’ll notice that we have another new method here: showSnackbar() . This is where our _scaffoldKey object will be used. This method will display status messages for our users at the bottom of the device screen. While this isn’t necessary for Firebase Phone Authentication, it is a nice feature for understanding what’s happening at different stages within our app.
Back in verifyPhoneNumber() , we’ll add our second callback object. This will listen for errors when verifying a user.
There are a couple common error messages that you might see while developing this app. The first one comes up if you have not enabled Firebase Phone Authentication in the console, have not added the SHA-1 signing key for your Android app, or are attempting to verify a phone number on an emulator.
The second comes up if you have attempted to use Phone Authentication on a non-test number too often within a short period of time (during testing I encountered this after about five uses within 30 minutes). This happens because Firebase will stop sending messages to numbers that are not on an allowlist, preventing users from being accidentally spammed by an app. It takes four hours for a number to become unblocked.
The next callback saves the verification ID generated by Firebase when an SMS is sent. This value will be required later when we want to sign our user in.
The final callback in verifyPhoneNumber() will notify our app when an SMS auto-retrieval times out, if supported by the device, and is also able to provide the verification ID for our app.
Once all of those callbacks are created, we can call verifyPhoneNumber() on our FirebaseAuth instance with the callbacks passed in as parameters alongside the device’s phone number and a timeout duration.
Now if we run our app, enter or import a real phone number, and click on the Verify Number button, we should get a text message from Firebase with a verification code. Keep in mind that a test phone number won’t trigger an SMS. Instead, you’ll have to enter the verification code you specified yourself when adding the test phone number to the allowlist to finish the Phone Authentication process.
Signing in
Now we just need to be able to do something with these codes. Let’s handle this by filling out our signInWithPhoneNumber() method. This will be surprisingly simple after building out verifyPhoneNumber() : we just need to create a new AuthCredential by passing in our verification ID and SMS verification code to Firebase’s PhoneAuthProvider , then call signInWithCredential on our FirebaseAuth instance to retrieve our user.
At this point we should be able to retrieve our verification code from an SMS, enter it into the Verification code field, and then click on the Sign in button to authenticate our user. It’s worth noting that we cannot use the autofill plugin here (at the time of this writing) to automatically retrieve the code. Unfortunately they require SMS code messages to start with a tag ( ), and Firebase does not allow the template for SMS messages to be changed, so this prefix cannot be added.
We should also be able to see our phone authenticated users in the Firebase console user list.
One fun thing to know here is that if our users aren’t English speakers, then we can use the setLanguageCode() method on our FirebaseAuth instance to change the language of the received SMS.
In this case I’m changing it to Mandarin Chinese, and the text message looks like this:
Anonymous Authentication
Now that we’ve gone over Firebase Phone Authentication, let’s take a look at Anonymous Authentication. This method is a bit unique in that it assigns each session-user an ID that uniquely identifies them to the Firebase backend, but isn’t a permanent authentication method — mainly because it isn’t really authenticating anyone. The main reason to use Anonymous Authentication is that it lets us create an onboarding experience for our users that doesn’t require them to create a permanent account immediately, removing some of the friction from your app experience.
This is, by far, the easiest of the authentication types that has been discussed in this series. Let’s start by adding a new Container and RaisedButton to our array in the build() method:
Now we just need to create the signInAnonymously() method. This will call signInAnonymously() on our FirebaseAuth instance, and then save our user.
Before we can sign our users in anonymously, we will need to return to the Firebase console and enable Anonymous sign-in
And that’s it — we can now click on the Anon Sign in button in our app. If we go back into our Firebase console, we should see our new anonymous user.
Non-Permanence
Before we finish this discussion on Firebase Phone and Anonymous Authentications, I wanted to bring up one important thing to consider when using these two types of logins. If the user logs out or changes devices, then their User UID will be completely new and they will not be associated with any previous UIDs that they may have used. If you have a Firebase database set up that relies on this UID to point to the user’s correct data, then they will no longer be able to access it. The best practice here is to attempt to get your users to log in with any of the methods that we’ve discussed in previous posts for a more permanent and secure user record. You can also link their current credentials (and thus their current UID) together with their new ID through the use of Firebase’s account linking feature, though a full discussion on using this with Flutter may be more appropriate for another article.
Conclusion
In this article we have discussed two ways that you can log in your users with Firebase: using Phone Authentication, and Anonymous Authentication. Both of these are great tools for quickly getting your users into your app before going through a longer account creation, though they are currently not substitutes for Firebase’s other, more robust, authentication systems. Hopefully by knowing these two techniques, you will be able to create a smoother and more pleasant app experience for your users.
Источник