E-Mail/Password Authentication with Firebase and Nuxt
Vannsl
Posted on October 19, 2019
You want to add Firebase to your Nuxt.js project? Here is how you can do that!
Environment
- node 12.10.0
- npm 6.11.3
- nuxt 2.10.0
- firebase (npm package) 7.2.1
The code snippets provided in this article are following the Prettier style guidelines.
Part Firebase
Create a project and set auth up
First, go to the Firebase Console and add a new project. Afterwards click on the Authentication link and manage the Sign-In Methods. You can choose between E-Mail/Password and various social network vendors.
Don't forget to whitelist the URLs domains on the same page. Usually you will need localhost
for running your Nuxt.js application in development and your custom domain for production.
You're already done with the setup!
Firebase SDK snippet
Either, head back to your project overview and select the web application option or go to Settings > General to copy the Firebase SDK snippet. You will need two things:
- The core Firebase JS SDK
- Your Web app's Firebase configuration snippet
Part Nuxt.js
Core SDK
The URL for the core Firebase JS SDK should be loaded upfront, so you should put it into the head
block. To do that in your Nuxt.js project, open the nuxt.config.js
and add the script to the head
object:
head: {
script: [
{
src: 'https://www.gstatic.com/firebasejs/[VERSION-NUMBER]/firebase-app.js'
}
]
},
Plugin
To add the Firebase configuration to your Nuxt.js project, you have to install the npm package firebase
and create a new plugin.
# Using npm
npm install firebase --save
# Using yarn
yarn add firebase
Create a new file firebase.js
(or any other name) in the ~/plugins
directory and add your Firebase configuration:
// ~/plugins/firebase.js
import firebase from 'firebase'
const firebaseConfig = {
apiKey: 'your-api-key',
authDomain: 'project-id.firebaseapp.com',
databaseURL: 'https://project-id.firebaseio.com',
projectId: 'project-id',
storageBucket: 'project-id.appspot.com',
messagingSenderId: 'messaging-sender-id',
appId: 'app-id'
}
const app = firebase.initializeApp(firebaseConfig)
export const db = app.database()
If you get the error
Firebase: Firebase App named '[DEFAULT]' already exists (app/duplicate-app).
you are initializing several instances of the Firebase App and should check if there is one before initializing a new one
The following code improves the plugin by checking if there is already an application initialized:
// ~/plugins/firebase.js
import firebase from 'firebase'
let app = null;
const firebaseConfig = {
apiKey: 'your-api-key',
authDomain: 'project-id.firebaseapp.com',
databaseURL: 'https://project-id.firebaseio.com',
projectId: 'project-id',
storageBucket: 'project-id.appspot.com',
messagingSenderId: 'messaging-sender-id',
appId: 'app-id'
}
app = firebase.apps.length
? firebase.app()
: firebase.initializeApp(firebaseConfig)
export const db = app.database()
If you're coding in TypeScript, don't forget to change the first line of the code snippet above to
import * as firebase from 'firebase'
.
Don't forget to register that plugin in your nuxt.config.js
:
plugins: ['~/plugins/firebase.js'],
That's it! The bridge between Firebase and Nuxt.js is done.
Authentication Example
To use the Authentication open your Vue SFC (Single File Component), located either in the directory ~/pages
or ~/components
depending on your project's structure.
In this file, first, you will need to import firebase in the <script>
block again:
// <script> block
import firebase from 'firebase'
// or when writing TypeScript
import * as firebase from 'firebase'
Now you have access to firebase
in this component. The API for authentication is accessible using the method auth()
. To check the current authentication state during the user's visit on the page, you can use onAuthStateChanged
in the created
lifecycle hook. The method returns a user object. It includes amongst other things the email address of the user.
// <script> block
asyncData() {
return {
authenticatedUser: null
}
},
created() {
firebase.auth().onAuthStateChanged(user => (this.authenticatedUser = user))
}
First, you will need to give the user the possibility to do a registration. Assuming the user should enter the password twice during registration the script looks like this:
// <script> block
asyncData() {
return {
email: '',
password: '',
registrationPassword: ''
}
},
methods: {
register() {
if (this.password === this.registrationPassword) {
firebase
.auth()
.createUserWithEmailAndPassword(this.email, this.password)
} else {
// display error message
}
}
}
Now you have to add the form in the <template>
block of your Vue SFC.
<!-- <template> block -->
<form @submit.prevent="register">
<input type="email" v-model="email" placeholder="Your email address" />
<input type="password" v-model="password" placeholder="Your password" />
<input type="password" v-model="registrationPassword" placeholder="Re-enter password" />
<button>Register</button>
</form>
Currently Firebase only accepts passwords with a minimum length of 6 characters.
The user is now successfully registrated. You can check the existance of the database entry in the Firebase console by clicking on Authentication > Users.
To provide some feedback for the user, you could show a message with the email address of the authenticated user. Also, you can present a logout button:
<!-- <template> block -->
<div v-if="authenticatedUser">
<p>You are logged in as {{ authenticatedUser.email }}.</p>
<p>Logout?</p>
<button @click.prevent="logout">Logout</button>
</div>
// <script> block
methods: {
logout() {
firebase.auth().signOut()
}
}
For login and logout you can call signInWithEmailAndPassword
with the email and the password.
<!-- <template> block -->
<form @submit.prevent="login">
<input type="email" v-model="email" placeholder="Your email address" />
<input type="password" v-model="password" placeholder="Your password" />
<button>Login</button>
</form>
// <script> block
methods: {
login() {
firebase.auth().signInWithEmailAndPassword(this.email, this.password)
}
}
Here is the full example of a simple Register-Login-Logout component:
<template>
<div>
<div v-if="authenticatedUser">
<p>You are logged in as {{ authenticatedUser.email }}.</p>
<p>Logout?</p>
<button @click.prevent="logout">Logout</button>
</div>
<div v-else>
<input type="radio" id="hasAccount" :value="false" v-model="needsAccount" />
<label for="hasAccount">I have an account</label>
<br />
<input type="radio" id="needsAcctouns" :value="true" v-model="needsAccount" />
<label for="needsAcctouns">I need an account</label>
<form @submit.prevent="loginOrRegister">
<input type="email" v-model="email" placeholder="Your email address" />
<input type="password" v-model="registrationPassword" placeholder="Your password" />
<input
v-if="needsAccount"
type="password"
v-model="registrationPassword"
placeholder="Re-enter Password"
/>
<button v-text="needsAccount ? 'Register' : 'Login'" />
</form>
</div>
</div>
</template>
<script>
import firebase from 'firebase'
export default {
name: 'Login',
asyncData() {
return {
authenticatedUser: null,
email: '',
password: '',
registrationPassword: '',
needsAccount: true
}
},
methods: {
register() {
if (this.password === this.registrationPassword) {
firebase
.auth()
.createUserWithEmailAndPassword(this.email, this.password)
} else {
// display error message
}
},
login() {
firebase.auth().signInWithEmailAndPassword(this.email, this.password)
},
loginOrRegister() {
if (this.needsAccount) {
this.register()
} else {
this.login()
}
},
logout() {
firebase.auth().signOut()
}
},
created() {
firebase.auth().onAuthStateChanged(user => (this.authenticatedUser = user))
}
}
</script>
That's it, you're done! 🎉
Next Steps
Next, you can add some validation and other cases. For example, if you try to register an email address that is already in the database you will get the error: uncaught exception: Error: The email address is already in use by another account
. Catch this exception and provide a message for the user.
- Case already registered
- Case forgot/reset password (with
firebase.auth.sendPasswordResetEmail
) - Add Authentication via social media vendors (e.g.
firebase.auth.GoogleAuthProvider()
- Split the component into multiple components.
Posted on October 19, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.