Building Simple CRM with Vue: Establishing Secure Sign Up Page Using Firebase Authentication
Tags: vue, tutorial, javascript, webdev
Published: 2024-03-05 15:55:57


![Establishing Secure Sign Up Page Using Firebase Authentication](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/az0qoa2df77m6zakke1k.png)

> Check [this post](https://webcraft-notes.com/blog/building-simple-crm-with-vue-establishing-secure) in [my web notes](https://webcraft-notes.com/)!

Welcome to the next phase of Vue CRM development, where we delve into the creation of essential components – Login and Sign Up pages. In this tutorial, we'll not only guide you through the process of crafting these crucial user authentication interfaces but also show you how to seamlessly integrate them with Firebase Authentication. By harnessing the power of Firebase Auth, we unlock a realm of benefits for securing user interactions in our Simple CRM. Let's embark on this journey to establish secure Login and Sign Up pages, leveraging the capabilities of Vue.js and Firebase Authentication.

Here is our plan for today's work:

### 1. Building Auth Layout and Configuring Nested Routes in Vue-Router
### 2. Designing Sign-Up Page in Vue.js with Vuetify
### 3. Creating the First Pinia Store
### 4. Firebase Authentication Integration in Vue CRM
Okay, we have a plan so let's stop talking and start working!

## 1. Building Auth Layout and Configuring Nested Routes in Vue-Router
Vuetify gives us ready-to-use forms that we can use in our sign-up or login page development, luckily those forms are going with popular validation libraries "Vee-Validate" and "Vuelidate" which simplify our work even more. Also, we can use only inputs and create our forms, I think we will use this variant in building "create products functionality".

So, let's create a new AuthLayout inside the layouts folder and add simple layout styles with a router-view template.
```
<template>
    <div class="main__content">
        <router-view />
    </div>
</template>
<script>
export default {
    name: 'AuthLayout'
};
</script>
```
Now, we need to modify our router settings, set additional layouts for auth pages, and add our sign-up page. For that import all pages and components inside the index.js file in the router folder and update routes similar to our MainLayout. The final version of my vue-router file:
```
import { createRouter, createWebHistory } from 'vue-router';
import MainLayout from '../layouts/MainLayout.vue';
import AuthLayout from '../layouts/AuthLayout.vue';
import SignUp from '../views/SignUp.vue';
import Dashboard from '../views/Dashboard.vue';
const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      component: MainLayout,
      children: [
        { 
          path: '', 
          component: Dashboard 
        },
      ],
    },
    {
      path: '/auth',
      component: AuthLayout,
      children: [
        { 
          path: 'sign-up', 
          component: SignUp
        }
      ],
    },
  ]
})
export default router
```
We can check updates, launch the dev server, and check /auth/sign-up route. We will see an empty sign-up page but it's ok, more important that all our layouts and routes are configured correctly.

## 2. Designing a Sign-Up Page in Vue.js with Vuetify
Next step, create the SignUpForm component in the components folder and check [the forms section](https://vuetifyjs.com/en/components/forms/) in Vuetify documentation. There is a part with [a vee-validate example](https://vuetifyjs.com/en/components/forms/#vee-validate), copy that example and paste it inside the SignUpForm component, do not forget to copy scripts also. Then add some more fields that we would like users to fil them with personal data.
```
<template>
    <form @submit.prevent="submit">
        <h3 class="mb-5">Sign Up</h3>
        <v-text-field
            v-model="name.value.value"
            :error-messages="name.errorMessage.value"
            label="Name"
        ></v-text-field>
        <v-text-field
            v-model="phone.value.value"
            :error-messages="phone.errorMessage.value"
            label="Phone Number"
        ></v-text-field>
        <v-text-field
            v-model="email.value.value"
            :error-messages="email.errorMessage.value"
            label="E-mail"
        ></v-text-field>
        <v-text-field
            v-model="password.value.value"
            :error-messages="password.errorMessage.value"
            label="Password"
        ></v-text-field>
        <v-text-field
            v-model="repeatPassword.value.value"
            :error-messages="repeatPassword.errorMessage.value"
            label="Repeat Password"
        ></v-text-field>
        <v-btn
            class="me-4"
            type="submit"
        >
            Sign Up
        </v-btn>
        <v-btn 
            color="indigo-darken-3"
            variant="flat">
            Already have an account?
        </v-btn>
    </form>
</template>

<script setup>
  import { ref } from 'vue'
  import { useField, useForm } from 'vee-validate'
  const { handleSubmit, handleReset } = useForm({
    validationSchema: {
      name (value) {
        if (value?.length >= 2) return true
        return 'Name needs to be at least 2 characters.'
      },
      phone (value) {
        if (value?.length > 9 && /[0-9-]+/.test(value)) return true
        return 'Phone number needs to be at least 9 digits.'
      },
      email (value) {
        if (/^[a-z.-]+@[a-z.-]+\.[a-z]+$/i.test(value)) return true
        return 'Must be a valid e-mail.'
      },
      password (value) {
        if (value?.length >= 8) return true
        return 'Password needs to be at least 8 characters.'
      },
      repeatPassword (value) {
        if (value === password.value.value) return true
        return 'Password and Repeat Password values should be equal.'
      },
    },
  })
  const name = useField('name')
  const phone = useField('phone')
  const email = useField('email')
  const password = useField('password')
  const repeatPassword = useField('repeatPassword')
  const submit = handleSubmit(values => {
    console.log('submit');
  })
</script>
```
And wait a minute, we need to install Vee-Validate into our project, just use "npm i vee-validate".

Great, now import our Form directly inside the SignUp.vue component that we need to create in the views folder, and restart the project.

Once again thank you "[UI Verse](https://uiverse.io/)" for fantastic free UI examples, with their help I added some styles to my sign-up page. Here is the result:
![Designing a Sign-Up Page in Vue.js with Vuetify](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eeczslukavvbmlmi147c.png)

Looks nice, now we need to implement the Firebase authentication module a save our user in Firebase auth.
## 3. Creating the First Pinia Store
We will create a new Pinia auth store specially for users. Add a new auth.js file to the store folder, then we need to import the "defineStore" method from pinia and use it for our first store creation.

If you want to learn more about how to work with pinia just check [this post](https://webcraft-notes.com/blog/vuejs-state-management-guide-pinia-in-practice).

Next, we will define the state section as an arrow function that will return our user state; an actions object that gonna have methods (like sign-up, log-in...) that we can call from different components of our project; and getters - access to our store state.
```
import { defineStore } from 'pinia';
export const useAuthStore = defineStore({
    id: 'auth',
    state: () => ({
        
    }),
    actions: {

    },
    getters: {
        
    }
});
```
Now we will add a user variable to our state that will store user data which we will receive from firebase authentication, gUser getter that will give us access to our user state, and finally "aSignUp" method into actions that will call the firebase auth and create new user. Okay, let's go to our next fire step.

## 4. Firebase Authentication Integration in Vue CRM
First of all visit [Firebase Console](https://console.firebase.google.com/), click on Authentication module to add it to our project, then choose "Email/Password Sign-in provider" (yes there are many more options but for now we will use only one) enable and save changes.
![Firebase Console Auth](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/56vop5if92qu49qfwn4k.png)

The Firebase Authentication module has a "[createUserWithEmailAndPassword](https://firebase.google.com/docs/auth/web/start)" method that we gonna use for new user creation.

Open the firebase.js file, import "getAuth" method, use it and export "auth as a result:
```
import { getAuth } from "firebase/auth";
export const auth = getAuth(app);
```
Open the auth store file, import the "createUserWithEmailAndPassword" method from "firebase/auth", and also import our "auth" module from the firebase file.

Now, inside the auth store create a new action "aSignUp" method that will call Firebase to create a new user. 

All that stuff gonna look something like this:
```
import { defineStore } from 'pinia';
import { createUserWithEmailAndPassword } from "firebase/auth";
import { auth } from '../firebase/firebase';
export const useAuthStore = defineStore({
    id: 'auth',
    state: () => ({
        user: null
    }),
    actions: {
        async aSignUp(form) {
            try {
                await createUserWithEmailAndPassword(auth, form.email, form.password)
                    .then(async (userCredential) => {
                        this.user = userCredential.user;
                    });
            } catch (error) {
                const errorCode = error.code;
                const errorMessage = error.message;
                console.log(errorCode,errorMessage);
            }
        }
    },
    getters: {
        gUser: (state) => state.user,
    }
});
```
Awesome! We can create new users now with our Sign-Up form.

Open the SignUpForm component and import the auth store then declare it as a variable. Then modify the handleSubmit function, just call the aSignUp method from the auth store.
```
import { useAuthStore } from '../../stores/auth';
const authStore = useAuthStore();
const submit = handleSubmit(values => {
    authStore.aSignUp({email: values.email, password: values.password});
})
```
And inside Firebase Console just check the result:
![Firebase result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oi3pk08lgtqurqrm971y.png)

We did it! Fantastic feelings when everything works as it should. Let's make some small conclusions and move to our next step.

In conclusion, we've successfully laid the foundation for a secure sign-up page in our Vue.js CRM, seamlessly integrating Firebase Authentication for user registration. By utilizing the powerful combination of Vue.js, Vuetify, Pinia, and Firebase, we've created a robust environment for managing user interactions. Stay tuned for further insights as we delve into additional functionalities and continue shaping our Simple CRM.