How to approve user registration with Firebase?

Viewed 2191

I have created a simple Vue app that has authentication, it allows the user to create an account, login with the created account and get access to the app after that. I want to make so that when a user creates an account I must approve him before he can login and get access to the home page I researched on how to do it but I didn't find anything, how can I do it?

Here is my Login:

<template>
  <div class="login">
     <form action="" class="form-signin">
    <h3 class="heading">Sign In</h3>
    <input type="text" placeholder="Email" v-model="email" class="form-control"><br>
    <input type="password" placeholder="Password" v-model="password" class="form-control"><br>
    <button @click="login" class="btn btn-lg btn-primary btn-block">Log In</button>
    <p>You don't have an account? You can <router-link to="/sign-up">create one here</router-link></p>

    </form>
  </div>
</template>


<script>
import firebase from 'firebase'

export default {
  name: 'login',
  data() {
    return {
    email: '',
    password: ''
    }
  },
  methods: {
    login: function () {
     firebase.auth().signInWithEmailAndPassword(this.email, this.password).then(
      (user) => {
        this.$router.replace('home')
      },
       (error) => {
         alert(`Ooops ${error.message}`)
       }
     )
    }
  }
}
</script>

My SignUp:

<template>
  <div class="sign-up">
    <form action="" class="form-signin">
    <h3 class="heading">Create a new account</h3>
    <input type="text" placeholder="Email" v-model="email" class="form-control"><br>
    <input type="password" placeholder="Password" v-model="password" class="form-control"><br>
    <button @click="signUp" class="btn btn-lg btn-success btn-block">Sign Up</button>
    <span>Already have an account?<router-link to="/login"> Sign in Here</router-link></span>
    </form>
  </div>
</template>


<script>
import firebase from 'firebase'
export default {
  name: 'signUp',
  data() {
    return {
      email: '',
      password: ''
    }
  },
  methods: {
    signUp: function () {
      firebase.auth().createUserWithEmailAndPassword(this.email, this.password).then(function(user) {
        alert('Your account has been created!')
      },
      function (error) {
        alert(`Ooops ${error.message}`)
      }
      )
    }
  }
}
</script>

My Home:

<template>
<div class="home">
  <h1>Welcome to the home page</h1>
  <button class="btn btn-danger" @click="logout">Logout</button>
</div>
</template>

<script>
import firebase from 'firebase'
export default {
  name: 'home',
  methods: {
  logout: function() {
  firebase.auth().signOut().then(() => {
  this.$router.replace('login')
  })
  }
 }
}
</script>

My Firebase configuration:

let app = ''
const config = {
  apiKey: 'AIzaSyDE0IVgepdhCOJLjcunmLN35AJ-6e0X0ak',
  authDomain: 'repti-care-90f1d.firebaseapp.com',
  databaseURL: 'https://repti-care-90f1d.firebaseio.com',
  projectId: 'repti-care-90f1d',
  storageBucket: 'repti-care-90f1d.appspot.com',
  messagingSenderId: '551446965940'
}

firebase.initializeApp(config)

firebase.auth().onAuthStateChanged(() => {
  if (!app) {
    app = new Vue({
      router,
      render: h => h(App)
    }).$mount('#app')
  }
})

And my router:

const router = new Router({
  routes: [
    {
      path: '/login',
      name: 'login',
      component: Login
    },
    {
      path: '/home',
      name: 'home',
      component: Home,
      meta: {
        requiresAuth: true
      }
    },
    {
      path: '/',
      name: 'login',
      component: Login

    },
    {
      path: '/sign-up',
      name: 'sign up',
      component: SignUp
    },
    {
      path: '*',
      redirect: '/login'
    }
  ]
})

router.beforeEach((to, from, next) => {
  const currentUser = firebase.auth().currentUser
  const requiresAuth = to.matched.some(record => record.meta.requiresAuth)

  if (requiresAuth && !currentUser) next('login')
  else if (!requiresAuth && currentUser) next('home')
  else next()
})

export default router
2 Answers

Use custom claims. That is the most secure way to do this as profile changes can be done client side without restrictions. Learn more about custom claims here.

You can define a security rule:

{
  "rules": {
    "adminContent": {
      ".read": "auth.token.approved === true",
      ".write": "auth.token.approved === true",
    }
  }
}

This will block user access to your side even though the user is signed in. Once the user is approved, you would call:

admin.auth().setCustomUserClaims(uid, {approved: true}).then(() => {
  // The new custom claims will propagate to the user's ID token the
  // next time a new one is issued.
});

Maybe create an extra flag at the user's profile on firebase and check that flag when he logs in. Set it to 0 if you have not approved and to 1 when you approve him. Basically you add a simple check.

Related