With the Nuxt Auth module, we can add authentication to our Nuxt app with ease.
One way is to add authentication with Firebase.
In this article, we’ll look at how to add Firebase authentication to our server-side rendered Nuxt app.
Install Packages
We have to add some packages to add Firebase to our Nuxt app.
To do that, we run:
npm i @nuxtjs/firebase @nuxtjs/pwa firebase firebase-admin
to add the required packages.
Configuration
We have to add configuration to our Nuxt app so that we can get the user when we load pages.
In nuxt.config.js
, we write:
export default {
/*
** Nuxt rendering mode
** See https://nuxtjs.org/api/configuration-mode
*/
mode: 'universal',
/*
** Nuxt target
** See https://nuxtjs.org/api/configuration-target
*/
target: 'server',
/*
** Headers of the page
** See https://nuxtjs.org/api/configuration-head
*/
head: {
title: process.env.npm_package_name || '',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: process.env.npm_package_description || '' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
/*
** Global CSS
*/
css: [
],
/*
** Plugins to load before mounting the App
** https://nuxtjs.org/guide/plugins
*/
plugins: [
],
/*
** Auto import components
** See https://nuxtjs.org/api/configuration-components
*/
components: true,
/*
** Nuxt.js dev-modules
*/
buildModules: [
],
/*
** Nuxt.js modules
*/
modules: [
// Doc: https://axios.nuxtjs.org/usage
'@nuxtjs/axios',
'@nuxtjs/pwa',
[
'@nuxtjs/firebase',
{
config: {
apiKey: "api-key",
authDomain: "project-id.firebaseapp.com",
databaseURL: "https://project-id.firebaseio.com",
projectId: "project-id",
storageBucket: "project-id.appspot.com",
messagingSenderId: 'message-sender-id',
appId: "BookDb"
},
services: {
auth: {
persistence: 'local',
initialize: {
onAuthStateChangedMutation: "SET_USER",
onAuthStateChangedAction: 'onAuthStateChangedAction',
},
ssr: {
serverLogin: {
sessionLifetime: 60 * 60 * 1000,
loginDelay: 50
}
}
}
}
}
]
],
/*
** Axios module configuration
** See https://axios.nuxtjs.org/options
*/
axios: {
},
/*
** Build configuration
** See https://nuxtjs.org/api/configuration-build/
*/
build: {
},
firebase: {
services: {
auth: {
ssr: true
}
}
},
pwa: {
meta: false,
icon: false,
workbox: {
importScripts: [
'/firebase-auth-sw.js'
],
dev: true
}
}
}
We add the @nuxtjs/firebase
module with many options.
The config
property has the Firebase configuration options.
services
configures the auth
service to persist the user.
The onAuthStateChangeMutation
action is the Vuex action to save the authenticated user’s data.
ssr
has the options for how long to keep the user data.
The sessionLifetime
property has the session lifetime.
And loginDelay
is the delay to save the user data after a successful login.
Vuex Store
We’ve to create a Vuex store to store the data.
To do that, we create a store/index.js
file and write:
export const state = () => ({
authUser: {}
})
export const actions = {
async onAuthStateChangedAction({ commit }, { authUser, claims }) {
const { uid, email, emailVerified, displayName, photoURL } = authUser
commit('SET_USER', {
uid,
email,
emailVerified,
displayName,
photoURL,
isAdmin: claims.custom_claim
})
},
async nuxtServerInit({ dispatch, commit }, { res }) {
console.log(res.locals)
if (res && res.locals && res.locals.user) {
const { allClaims: claims, idToken: token, ...authUser } = res.locals.user
await dispatch('onAuthStateChangedAction', {
authUser,
claims,
token
})
commit('ON_AUTH_STATE_CHANGED_MUTATION', { authUser, claims, token })
}
}
}
export const mutations = {
ON_AUTH_STATE_CHANGED_MUTATION(state, { authUser, claims }) {
const { uid, email, emailVerified, displayName, photoURL } = authUser
state.authUser = {
uid,
displayName,
email,
emailVerified,
photoURL: photoURL || null,
isAdmin: claims.custom_claim
}
},
SET_USER(state, payload) {
console.log(payload)
state.authUser = payload;
}
}
The onAuthStateChanged
action is invoked by nuxtServerInit
to set the authenticated user’s data on page load.
nuxtServerInit
is run when the page loads.
ON_AUTH_STATE_CHANGED_MUTATION
is a mutation to save the authUser
state.
SET_USER
sets the authUser
state.
When we run the this.$fireAuth.signInWithEmailAndPassword
method is run successful by authentication with the correct credentials, then the actions and mutations will be run.
The res.locals.user
property in the nuxtServerInit
will also be set so that we have the currently logged in user’s data on page load.
Login Form
Finally, we need a login form so we can log in.
We create a login.vue
file and add:
<template>
<div class="container">
<form @submit="signIn">
<div>
<label>Username</label>
<input type="text" v-model="login.email" />
</div>
<div>
<label>Password</label>
<input type="text" v-model="login.password" />
</div>
<div>
<button type="submit">Submit</button>
</div>
</form>
</div>
</template>
<script>
export default {
data() {
return {
login: {},
};
},
methods: {
async signIn() {
try {
const { email, password } = this.login;
await this.$fireAuth.signInWithEmailAndPassword(email, password);
} catch (error) {
console.log(error);
}
},
},
};
</script>
We create a login form and if we log in with the right email and password, the Vuex actions will be run to set the data.
This is because the static/assets/firebase-auth-sw.js
service worker that comes with the Nuxt Firebase does that work for us in the background.