Passwordless sign-in, via email link, with Firebase and Vue.js

Axel Hodler
Level Up Coding
Published in
4 min readMay 24, 2020

--

Image by kopcan on Pixabay

By using a password manager the handling of sign up and log in is easy. Although not all the time. Some sites restrict the length or do not allow some characters. In addition the autofill does not always work, which requires us to copy and paste passwords around.

Not everyone uses password managers. As a result the same password is used for multiple sites. Or written down on paper or as a digital note.

Medium supports the login with just an email address. No password. The troubleshooting, at the time of this writing, mentions they do not support passwords.

Setting up the same using Firebase Authentication is possible.

Under the Tab Sign-in method in Authentication enable Email link

In our Vue.js app we need to be able to trigger two actions. First sending the sign in link to an email address the user has entered. Then sign-in the user if he opens the app through that link.

The article expects we have already added the Firebase dependency and the credentials for our project. If not we find the setup in the documentation.

As for sending the link we use the Firebase auth module.

Sending the link

Running the function will send the link to the email provided with the parameter. We also need to store the used email because we will need it in the next step. If we are using vuex, we can wrap the function above.

Making sure we store the email for later

Instead of using vuex state, we could also store it directly in localStorage or somewhere else.

In the route specified in actionCodeSettings we need to handle users coming back with a link they got via email.

The link contains the apiKey, a one time code to identify the request, and the url specified in actionCodeSettings

https://appname.firebaseapp.com/__/auth/action?
apiKey=${APIKEY}&
mode=signIn&
oobCode=${OOBCODE}&
continueUrl=${URL}&
lang=en

In the created() step of the Vue.js lifecycle we can check the current url. Using location.href and passing the result to isSignInWithEmailLink . If it is a sign in link, we sign the user in.

Sign in the user after checking whether it is a sign in link

Again we get the previously stored signInEmail to use with signInWithEmailLink.

There is a lot of logic in the created() we should extract it into services after making it work.

Sign in works.

These two steps:

  • Send link to email
  • Auth user if entering app via the link

are what is called the happy path.

There are some issues we should handle too.

User opens link with a different browser than the one used to request the link

What might seem like an edge case on Desktop, a user requesting the link on Chrome and then opening it with Firefox, could happen more often on mobile.

If we are using a QR code to get the users to the app. An iOS user will scan the QR code with the camera app. The camera app will open Safari. The user then uses his Gmail address to request the email link. Opening the link in the Gmail app would open Chrome if installed. But we have stored the signInEmail in Safari. The sign in is not possible without prompting the user again for his email even though we have a valid link.

We would explain the issue at hand to the user. Ask for the email again. Then trigger signInWithEmailLink. The code above would need to be changed to both check if it is a valid link and if the signInEmail is present.

The code in created() could change to

Asking the user for the email to continue with the link

If the user would now provide a different email it would lead to an error.

The sign in link was already used

Firestore will provide an error with code auth/invalid-action-code on an attempt to sign in with the link a second time. We would need to tell the user to attempt a sign in again. The link is only valid one time.

Emails containing the sign in link do not arrive

The issue arises for some mail providers.

A solution is to provide your own SMTP Settings in Authentication under the Templates tab

We would configure Firebase to use our own mail server. Not a big issue since we might already have one to receive emails to addresses of our domain.

Customising the email template

The mail used to send the links looks as follows by default

Hello,We received a request to sign in to appname.com using this email address. If you want to sign in with your mail@mail.com account, click this link:Sign in to appname.comIf you did not request this link, you can safely ignore this email.Thanks,Your appname.com team

Clicking the sign in link will lead to you to the page provided in actionCodeSettings above with the added url parameters.

Customising the mail is not possible to avoid abusing it for spam. We could just replace the content with our commercial and send it to every email we know via sendSignInLinkToEmail. Firebase does not want that.

To customise it we would need to implement the sign in flow by ourselves.

Something we probably do not want. And the reason why we use Firebase Auth in the first place. In the beginning the mail above should be enough.

--

--

Building things. Usually by writing code. www.hodler.co. Software Engineering @porschedigital