[AUDIO LOGO]
PETER FRIESE: They say there is no second chance
to leave a first impression.
And yet there are so many apps that
require creating an account before you can even
start using them.
Asking users to create an account
and come up with a strong password adds a lot of friction
to the onboarding process.
And many users won't even end up creating an account.
They will just uninstall your app.
Remember, on the app store, your competition is just a tap away.
So if you want more users to give your app a fair chance
and experience all the amazing features you poured
your heart into, you should remove the speed bump
and make the onboarding process as smooth as possible.
Hey, my name is Peter.
I'm a developer advocate on the Firebase team.
And today I'm going to show you how
you can streamline the onboarding process of your app
and reduce the number of people who
uninstall your app before even giving it a try.
So why should you ask your users to authenticate
in the first place?
Well, there are a number of reasons.
For example, you might need a way
to get in touch with your users, for example, by email
or by sending them an SMS.
If you're developing an app for a delivery service or a ride
sharing app, you might even want to be able to call your users.
Another very common reason is that you
need some unique identifier that you
can use as a key for the data you
store in the app's back end.
For example, if your app is a cross-platform to-do list app,
you want to make sure that your app can tell the to-dos of all
your users apart.
It would be a data-privacy disaster
if someone else would be able to see your to-dos,
and vise versa.
The same applies for a bank that needs
to make sure only the account user gets access
to that banking account.
Another reason for putting up an authentication speed bump
might be to artificially limit the number of people
who can use the app and create scarcity.
Or maybe your app is an app in front and for a resource that
requires some form of authentication,
like the machines in a factory.
All of these are valid reasons for asking your users
to sign in.
But not all of them require an upfront authentication.
So here is the demo app we've been
building in the past couple of videos
about Firebase authentication.
In all of the past videos, we've asked the user
to sign in before they can even start using the app
to track their favorite number.
And that makes sense if you want to use their user
ID as a key for data store in the back end.
Our app will hopefully be used by thousands
of users who want to track their favorite number.
And we need a key to identify which favorite number belongs
to which user.
But I am here today to tell you that we don't actually
need to ask our users to create an account before they
can start using the app.
So in this specific version of the app,
the user can start using the app without first signing in.
And still, all of that data will be stored in Cloud Firestore,
using a unique key which helps the app tell my data apart
from your data.
What's more, when the user really likes the app
they can then sign in, which gives them
a number of benefits.
For example, they can sign into the app on another device
to access the same data.
To make this work, I've implemented anonymous auth
and account linking in the app.
Anonymous auth allows users to start using the app
without having to sign in.
You can think of this as guest accounts.
Account linking, on the other hand,
allows your users to sign into your app
with multiple authentication providers.
For example, a user might sign into your app with email
and password first but later decide
they would rather sign in using Google sign-in
or sign in with Apple.
Account linking allows you to connect
different authentication credentials
and roll them into a single user account.
Bringing anonymous auth and account
linking together like this allows
us to implement a smooth onboarding flow like the one
I just showed you.
Let's first implement anonymous auth in our app.
If you want to follow along, you will
find the starter app in the GitHub repository
for this video.
The link is in the description below.
All right.
So anonymous authentication is one of the many authentication
mechanisms that Firebase R provides out of the box.
When a user of your app uses a feature of your app
that requires authentication, called auth.signinanonymously
to sign them in anonymously, this
will create a new Firebase user with a user ID
that is unique to your project.
But other than a user who signed in using, say, email
and password authentication or signed
in with Apple, an anonymous user doesn't
have any personally identifiable information on them.
Their UID is completely random and not connected
to the person's identity or the identity
of their device in any way.
You can use the UID as a key for any data
that you want to store for this user.
In our sample app, we want to let
users store their favorite number in the cloud.
So we need to add a user ID property to the Firestore
document that we use to store this data.
Depending on the use case of your app,
you might store other kinds of data.
For example, your app might be a photo-sharing app.
And you might be using cloud storage
to store your users photos.
You can use the user's UID as part
of the path to all their photo files
and store all of the user's photos in the same folder.
To allow users to start using your app without having
to create a new-user account, call it sign-in anonymously
as early as possible in the lifecycle of your app.
But first, it's a good idea to check if there already
is a logged-in user.
This will be the case if the app was launched before.
In this case, there would be an anonymous user
who is already signed in.
Or the user signed in using one of the other authentication
providers.
Either way, if there already is a user account,
we don't need to sign in anonymously again.
But if the current user property is nil, no user has signed in.
And we should call sign in anonymously
to create an anonymous account.
Since this is an asynchronous call,
we will have to call it using a wait.
Doing so will suspend the current function.
This makes sure the application doesn't
freeze while we're waiting for the result of this operation.
And if the call succeeds, the user is signed in anonymously.
And in case the call throws an error,
we will assign the error message to the error message property
on the view model to let the user know something went wrong.
Now, you might be wondering why we don't
use the result of this call.
The reason is that we have registered
an authentication state listener which
will react to any authentication state changes.
So whenever a user signs into our app or signs out again,
this piece of code up here will be run.
This allows us to centralize any code that updates the UI state,
based on whether a user is signed in.
Using anonymous authentication is
the first step to implementing a smooth onboarding experience.
But there is more.
Users might want to be able to use
the app on their other devices or share some of their data
with friends and family.
For both of these use cases, we need
to be able to refer to the user's data
by using their user ID.
And that means we need to be able to have
a human-readable handle that we can
use to refer to this account.
This will require upgrading their anonymous account
to a permanent account.
To achieve this, the user will have
to authenticate using another authentication mechanism.
For example, Google sign in, sign in with Apple,
or any other of the authentication providers
supported by Firebase authentication.
Once a user has successfully authenticated
using one of these providers, we can link their credentials
to the existing anonymous account.
Upgrading an anonymous account to a permanent account
in this way ensures that all of the user's data
will still be accessible to them.
This works because the upgraded account
will keep the UID of the anonymous account.
Let's see how we can implement this in our sample app.
A good place to upgrade the currently
signed-in anonymous account to a permanent account
is the sign-up screen.
When the user uses one of the authentication mechanisms
provided by the screen, we will then
use the resulting credentials and link them
to the anonymous account.
Let's implement this for email and password authentication.
First, we will use the email auth provider
to create an auth credential for the email
and password the user typed into the signup form.
We will then check if there actually
is a currently signed-in user.
If there isn't, something is seriously wrong with our app.
And we will throw a fatal error.
We'll then call the link with credential function
on the anonymous user to link this email and password
credential to the anonymous user.
This will effectively upgrade the anonymous user
to a permanent user account that can now
sign in using the email and password credential provided
by the user.
Since the authentication state of the logged-in user
didn't change--
they are still signed in, after all-- the authentication state
listener will not be triggered.
This means we will have to extract the updated user
account from the result of this call
and assign it to the user property on the view model.
And, finally, we will return true to let
the caller know that linking the account succeeded.
Let's run the application one more time
to see the result of our work in action.
First, reset the simulator to make
sure we've got a clean slate and to prove
that we are running the application for the very
first time.
Once the application has launched,
we see the main screen with the picker
for the user's favorite number.
At the bottom of the screen we see that we're
using the app as guest user.
I've refreshed the list of users in the Firebase console.
And we can see that there is an anonymous user with this UID.
I'll change the favorite number to 17.
And a quick look at Firestore shows us
that there is a Firestore document with this number.
And its user ID field contains the UID of the anonymous user
that's signed into the app.
I will tap in on the Login button to open the login view.
To link the anonymous account to an email address,
I flip over to the signup page and enter
the email address of the user I want to sign in as
and pick a password.
When I tap on sign up, the app links these credentials
to the anonymous account and dismisses the signup form.
Back on the main screen, we can see
that we're now signed in using this email address.
Let's take a quick look at the profile view
to see more details about the signed-in user account.
Since this account is now linked to the email address
I provided when signing in, it no longer
is an anonymous account.
And, consequently, it's not a guest account anymore.
Let's double check this by looking
at the Firebase console.
And, sure enough, we can see that the user with this UID,
which used to be an anonymous account,
now has an email address as its identifier.
And the only authentication provider linked to it
is the email authentication provider.
To demonstrate that the data stored in Firestore
can now be accessed from any of the user's devices,
I will launch the same app on a second simulator.
Again, this is a fresh simulator so the app hasn't
been run on this device before.
Once the app launches, we're assigned
as a different anonymous user.
Let's open the login form and sign in using the email address
and password we just used.
Once I hit log-in we are signed in as FredFirebase@gmail.com
on both devices.
And we can see Fred's favorite number on both devices.
Any changes I make on one of the devices
will be reflected on the other one and vice versa.
Great.
You just saw how to use account linking
to upgrade an anonymous user to a permanent user.
But account linking also works in other scenarios.
For example, when a user first signs
in using email and password authentication
but would then like to sign in using a federated identity
provider like Google sign in or a sign in with Apple,
you can use the same approach.
You first need to make sure the user has
signed in using their original authentication mechanism.
Then you ask them to authenticate
using one of the other authentication providers you
support in your app, and link the credentials returned
from the provider to the existing account.
For more details about this, check out
the documentation, specifically the section
about verified email addresses.
So there you have it.
We've optimized the onboarding experience for our users
by using anonymous auth and account linking.
Removing the need to sign in or create a user
account before being able to use the app
reduces friction and makes it much more likely that people
will actually use your app.
So the next time you implement authentication in your app,
consider using this approach.
As always, the source for the sample app
is available on our GitHub repository.
And the link is in the description below.
If you've got any questions, leave them in the comments
below or hit me up on social media.
I am @PeterFriese on Twitter and @PeterFriese@iosdev.space
on Mastodon.
Stay safe and I will see you in the next one.
[AUDIO LOGO]