Using Firebase Auth’s Email Link Login with SwiftUI

Nick Cooke
Firebase Developers
9 min readAug 13, 2020

--

Firebase Auth offers a variety of ways to authenticate users. Today, we are going to be discussing Email Link authentication, also known as Passwordless sign in. We will also implement Email Link authentication with SwiftUI, making use of the new SwiftUI life cycle APIs that Apple introduced at WWDC 2020.

So what is Email Link authentication? Firebase Auth can authenticate a user with just their email, no password required! Upon entering an email address, Firebase will send a special sign-in link to that email. A user can click the link in the email to sign in, which also verifies their email.

There are many benefits to using Email Link Authentication. For one, it creates a low friction sign up and sign in experience. Login screens can appear as an obstacle to users excited to use your app. With Email Link, users do not need to create a password to sign up or use one at login. All users need is a valid email address. It’s fast, easy, and efficient. Plus, users can always upgrade their account to login with a password or auth provider like Google, Facebook, or Apple.

As mentioned earlier, we are going to implement Email Link in a pure SwiftUI app. So, enough talk, let’s get started!

A white screen with one textfield for the user’s email and a button that will send our verification sign-in link.
This is what the final product will look like.

Preparing the Project

This guide offers step by step instructions for building a SwiftUI app that uses Email Link authentication. If you are not building the demo app as you follow along, feel free to start at the section of your choosing.

Setup our Xcode Project

Create a new Xcode project and select the iOS App template. I’ll be naming it PasswordlessSwiftUIApp. Select SwiftUI for the app’s Interface and Life Cycle. Make note of the bundle identifier used as we will use this to add this app to the Firebase project we will be creating.

Start by setting up the Xcode project.

Alright, awesome! Now that we have an Xcode project up and running, let’s set up our Firebase project on the Firebase Console.

Creating a project on the Firebase Console

Navigate to the Firebase Console and create a new project. I’m going to be naming it passwordless-swiftui. Since we will be building an iOS app in conjunction with this project, let’s go ahead and add an iOS App to our project. When prompted for the bundle identifier of our iOS app, we will use the bundle identifier from the Xcode project we set up in the previous section. Be sure to download the GoogleService-Info.plist and add it to your Xcode project. When adding the Firebase SDK in the Podfile, include both the Firebase/Auth and Firebase/DynamicLinks pods.

Add an iOS app to the Firebase project.

Connecting our app with Firebase

With an Xcode project set up and the Firebase Console configured, let’s connect the two! There are a few ways to configure the FirebaseApp in the new SwiftUI life cycle. The new @main attribute marks the entry point into our app. We will add an initializer for our app and configure Firebase there. It’s also worth noting that our app conforms to Apple’s new App protocol.

We should now be able to build and run our app. When our app launches, we will see the default “Hello, world!” text view that Xcode generated in our ContentView.

With our app up and running, let’s set up Email Link authentication!

Setting up Email Link Authentication

Email Link authentication uses Dynamic Links when creating the special sign-in link emailed to a user. As part of setting up Email Link Authentication, we will also need to set up Dynamic Links.

Enabling Email Link

Let’s enable Email Link authentication. Navigate to the project we set up earlier on the Firebase Console, go to the Authentication dashboard, and select the Sign-in method tab. Select Email/Password and enable both the Email/Password and Email Link toggles.

Enable the above toggles on the Authentication dashboard.

Configure Dynamic Links on the Firebase Console

Navigate to the Firebase project’s Settings. Scroll down to Your Apps and fill in an App Store ID and Team ID. These fields are required when setting up Dynamic Links.

While the App Store ID can be arbitrary, ensure the Team ID corresponds to a valid Team ID for an account registered in the Apple Developer Program.

Next, navigate to the Dynamic Links dashboard. After enabling Dynamic Links, you will be prompted to set up a URL prefix. I’ll be using passwordlessswiftui.page.link. If this were a real app, you would would want to pick something that’s closely associated with the app in your firebase project. Perhaps a subdomain, like signin.your-domain.com. Please visit the documentation for more details!

Next, we will create a Dynamic Link to use in the authentication process.

Click New Dynamic Link. Let’s walk through the creation steps:

  1. First, set up the short link for our new Dynamic Link. For the URL Prefix, choose something like demo or login. These prefixes are subject to availability.
  2. For the full Dynamic Link, we need to provide a deep link for deep linking into our app. This needs to be a valid domain that is authorized by Firebase. Luckily, Firebase already sets some up for us to use, and we can even add custom ones. In a new tab, navigate to the Authentication dashboard of the Firebase project and go to the Sign in method tab. Scroll down to Authorized Domains and copy one. Now, go back to where we were creating the Dynamic Link and paste in the copied domain for the long dynamic link. Be sure to prefix this link with https://. Then, give the Dynamic Link a name like Login Demo.
  3. Next, we need to define our Dynamic Link’s behavior for our iOS App. Select Open the deep link in your iOS App and select our iOS app in the drop down menu.

At this point, we have filled out enough information. Click the blue Create button! The gif below visualizes the above process.

Configure Dynamic Links in Xcode

There is one more step to configuring Dynamic Links. We need to make our app know that the Dynamic Link we created should link back to the app when opened. Go back to the Xcode project and navigate to the project’s Targets. Select the app’s target and go to the Signing and Capabilities tab. We need to enable the Associated Domains capability in our app. Click the + Capability button, and select Associated Domains. Add the URL prefix you set up on the Dynamic Links dashboard.

In my case, it looks like: applinks:passwordlessswiftui.page.link

At this point, we have successfully set up Email Link Authentication (and Dynamic Links in the process). 🎉

Implementing Email Link Authentication

Sending the verification link

Let’s set up our UI to include a textfield and a button. We will start with this:

The idea is that a user can enter their email into the CustomStyledTextField (1) and when they tap the CustomStyledButton, a verification email containing the special authentication link is sent to the provided email. (2)

Check out the code for theCustomStyledTextField and CustomStyledButton views below:

Firebase Auth makes it simple and easy to send a sign in link:

Let’s explain what’s going on:

  • First, we created an ActionCodeSettings object which is used to set and retrieve settings related to handling the authentication process. We set the url property to the dynamic link we set up on the Firebase Console. Here, we are using the short link we created. (1)
  • Then, we use Firebase Auth’s sendSignInLink(toEmail:actionCodeSettings:completion:) method to send the sign-in link to the email entered in the textfield! (2)
  • If there is an error, we build an AlertItem and set it as the value for our alertItem property. Because alertItem is marked as a @State property, SwiftUI may re-render the view when alertItem takes on a new value. When this occurs, the .alert(item:content:) view modifier will display an Alert if alertItem's value changes to a non-nil value. (*)

Filling out the text field and tapping the button will now send a verification email to the specified email address. The verification email follows a standard format and can be further customized on the Firebase Console.

SwiftUI’s new link handling view modifier

In iOS 14, Apple is providing developers with the new onOpenURL view modifier. It allows developers to provide a handler to a view that is invoked when the view receives a URL from the window or scene that the view is in. In the handler we provide, we can handle the incoming URL by modifying the state of our view accordingly. When compared to how deep links were handled when using AppDelegate or SceneDelegate, this new view modifier changes everything! Most importantly, since handling deep links usually involves making state changes that affect your app’s UI, the new modifier allows you to handle these state changes directly on the view you wish to modify for cleaner, more localized code.

Remember how Email Link authenticates users by sending them a verification email with a special link? Well this special link is a Dynamic Link that should deep link users back into our app. The special link used to deep link back into our app will contain information we will use to complete the authentication process. So to handle the link when we deep link back into our app, we will use onOpenUrl!

In this snippet, we finally get to handle the sign-in link when the user opens it and deep links back into our app. Let’s break it down:

  • For the purposes of this app, when the user signs in, we are going to present an orange modal view welcoming the user. We have added a @State property isPresentingSheet to represent if the modal sheet is presented. Initially, it is false because the user is not signed in. (1)
  • We then add the onOpenURL modifier to the NavigationView holding this view’s child views. (2)
  • To handle the incoming URL, we take the string value of the URL and pass it to Auth’s isSignIn(withEmailLink:) method. (3)
  • If the incoming link is a valid sign-in link, then we will want to use it to identify the user we want to sign in. To do this, we call the passwordlessSignIn(email:link:completion:) helper method and provide both the email the sign-in link was sent to as well as the special link we have opened in our app. (4) In passwordlessSignIn’s completion handler, we update isPresentingSheet to whether or not authentication was a success.
  • Since isPresentingSheet is a @State property, the line marked with a (5) will reevaluate when isPresentingSheet changes. If authentication was a success (and isPresentingSheet is now true), then we present the SuccessView to welcome our user. You can view the code for the SuccessView here.
  • If an error occurs during the authentication process, we build an AlertItem and set the alertItem property to it. When alertItem's value changes to a non-nil value, our ContentView displays an Alert view displaying the AlertItem. (6)

Let’s see our app in action

With everything set up, let’s build and run our app. Enter a valid email address and tap our CustomStyledButton. Next, switch out of the app to check for the email. You should have received an email from the app’s Firebase account. Inside the email is a verification link. Tapping it redirects you back to our app where an orange view will present itself if the authentication is successful. Also, if you navigate to the Authentication dashboard of the Firebase Console, you will see that a new user shows up in our user database!

Closing thoughts

Today, we learned about both Firebase and SwiftUI. We created an app with Firebase that uses the new SwiftUI life cycle. We also learned how to implement Email Link Authentication using the onOpenURL view modifier introduced in iOS 14 . Last, we demystified how to set up Dynamic Links for Email Link Authentication.

Thanks for reading! If you have any questions or comments, feel free to drop them in the discussion section below or on the GitHub repo for this project. For more information about Firebase and how you can use it to improve your app, start here!

--

--