skip to Main Content

I was working on a project which has an admin side, an admin could add another admins, and when an admin A add an admin B it automatically signin the admin B, so after many researches I found that firebase doesn’t provide any way to prevent or disable this behavior.

3

Answers


  1. Chosen as BEST ANSWER

    So I wanted to find the best solutions for a perfect user interaction, as we say features comes to fix bugs, So here is my alternative solution to hide this 'bug' :

    1. Before everything, we want to save our current admin's email in a state.
    2. When we click the submit button, we create a new admin B like usual cases.
    3. When admin B has been created successfully we open a dialog box and we ask admin A to confirm this action by providing his password (like a security check) on a password field inside the dialog box. 4.Now we have all credentials of admin A as shown in step 1 (email) and step 3 (password). 5.Now we can call signin method and sign the admin A back.
      Now let's write it in code (I'm using Rreact and @mui/material in my frontend) :

    Frontend :

    <TextField
      fullWidth
      label="Email"
      type="email"
      onChange={(email)=>{setEmail(email.target.value)}}
    />
    <TextField
      fullWidth
      label="Password"
      type="password"
      onChange={(pass)=>{setPassword(email.target.value)}}
    />
    <Button
     onClick={createNewAdmin}
    />
    <Dialog open={showDialog}>
      <DialogContent>
        <DialogContentText>
          Tap  your password !
        </DialogContentText>
        <TextField
            label="Password"
            type="password"
            onClick={(pass)=>setReAuthPass(pass.target.value)}}
          />
      </DialogContent>
      <DialogActions>
       <Button onClick={signAdminBack}>
        Confirm
       </Button>
      </DialogActions>
    </Dialog>
    

    State :

    const[email, setEmail] = React.useState('');
    const[password, setPassword] = React.useState('');
    const[oldEmail, setOldEmail] = React.useState('');
    const[reAuthPass, setReAuthPass] = React.useState('');
    const[showDialog, setDialog]=React.useState(false);
    
    

    Functions :

    const createNewAdmin=()=>{
       const auth = getAuth();
          //saving the current admin email
          setOldEmail(auth.currentUser.email);
          createUserWithEmailAndPassword(auth, email, password)
            .then((userCredential) => {
             //opening the dialog
             setDialog(true);
            }).catch((error)=>{console.log(error);});
    }
    
    const signAdminBack=()=>{
      const auth=getAuth();
      signInWithEmailAndPassword(auth, oldEmail, reAuthPass).then((userCredential)=>{
              //admin A brought back
              //closing the dialog
            }).catch((err)=>{
              console.log(err);
            });
    
    }
    

    Images
    enter image description here

    Bringing back the old admin


  2. It’s not recommended to create admin accounts on the front end as anyone could look into the code and action it themselves. You would want to create sufficient rules in the Firebase console to prevent users from editing other accounts etc. In fact, creating any new accounts but your own in the front end. This should all be controlled by Firebase’s Authentication service.

    If you want to create an admin account, create a cloud function to do that and then just call the cloud function. Something like this:

    My cloud function – I use custom user claims to make someone an admin as opposed to saving a ‘isAdmin’ property in the user’s document in firestore:

    exports.addAdminRole = functions.region('your-region-here').https.onCall((data, context) => {
      if (context.auth?.token.superAdmin !== true) { //-- Here it checks if the person making the call is an admin (or super admin) user
        return { error: 'Only super admins can add other admins.' }
      }
      return admin.auth().getUserByEmail(data.email).then(user => { // replace this getUserByEmail with creating a new user if needed
        return admin.auth().setCustomUserClaims(user.uid, {
          admin: true
        });
      }).then(() => {
        return {
          massage: `Success, ${data.email} has been made an admin.`
        }
      }).catch(err => {
        return err;
      });
    });
    

    Then you can call this function from your app:

    makeAdmin(adminEmail: string) {
        const callable = httpsCallable(this.functions, 'addAdminRole')
        callable({ email: adminEmail }).then(result => {
          console.log(result);
        })
      }
    

    Note that my example takes an existing user and makes them an admin, you can just replace the get user with create user and then set the customerUserClaim and even trigger an email at this point to them if you want to be fancy. Let me know if this helped.

    Login or Signup to reply.
  3. I think I’ve got the perfect solution (for vanilla JavaScript),

    while creating the user itself you can use the signOut(auth) for preventing default signing in to the newly created user

    import { initializeApp } from "https://www.gstatic.com/firebasejs/9.19.1/firebase-app.js";
    
    import {
    getAuth,
    createUserWithEmailAndPassword,
    signOut,
    } from "https://www.gstatic.com/firebasejs/9.19.1/firebase-auth.js";
    
    // Initialize Firebase
    const app = initializeApp(firebaseConfig);
    
    const auth = getAuth(app);
    
    button.click(() => {
    createUserWithEmailAndPassword(auth, email, Password)
    .then((res) => {
    signOut(auth);
    });
    });
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search