Firebase推出了当前用户

时间:2016-05-30 03:28:34

标签: javascript firebase firebase-authentication

所以我有这个问题,每当我添加一个新的用户帐户时,它就会启动已经登录的当前用户。我读了firebase api,它说" 如果新帐户创建后,用户自动登录" 但他们从未说过任何其他有关避免这种情况的内容。

      //ADD EMPLOYEES
      addEmployees: function(formData){
        firebase.auth().createUserWithEmailAndPassword(formData.email, formData.password).then(function(data){
          console.log(data);
        });
      },

我是管理员,我在我的网站中添加了帐户。如果我可以添加帐户而无需退出并登录新帐户,我希望如此。我能以任何方式避免这种情况吗?

17 个答案:

答案 0 :(得分:75)

更新20161110 - 以下原始答案

另外,请查看this answer以了解其他方法。

原始回答

这实际上是可能的。

但不是直接的,这样做的方法是创建第二个auth引用并使用它来创建用户:

var config = {apiKey: "apiKey",
    authDomain: "projectId.firebaseapp.com",
    databaseURL: "https://databaseName.firebaseio.com"};
var secondaryApp = firebase.initializeApp(config, "Secondary");

secondaryApp.auth().createUserWithEmailAndPassword(em, pwd).then(function(firebaseUser) {
    console.log("User " + firebaseUser.uid + " created successfully!");
    //I don't know if the next statement is necessary 
    secondaryApp.auth().signOut();
});

如果您没有指定用于操作的firebase连接,则默认情况下将使用第一个连接。

Source用于多个应用引用。

修改

对于新用户的实际创建,除了管理员之外没有人或其他人在第二个auth引用上进行身份验证并不重要,因为创建一个帐户所需要的只是auth引用本身。

以下内容尚未经过测试,但需要考虑

你必须考虑的事情是将数据写入firebase。通常的做法是用户可以编辑/更新自己的用户信息,因此当您使用第二个auth引用进行编写时,这应该可行。但是,如果您拥有该用户的角色或权限,请确保使用具有正确权限的auth引用来编写该角色或权限。在这种情况下,主auth是admin,第二个auth是新创建的用户。

答案 1 :(得分:16)

更新20161108 - 原始答案

Firebase刚刚发布了firebase-admin SDK,它允许服务器端代码用于此和其他常见的管理用例。阅读installation instructions,然后深入documentation on creating users

原始回答

目前无法做到这一点。创建电子邮件+密码用户会自动在新用户中签名。

答案 2 :(得分:3)

我刚刚创建了一个Firebase函数,该函数会在创建Firestore文档时触发(规则仅对管理员用户具有写权限)。然后使用admin.auth()。createUser()正确创建新用户。

export const createUser = functions.firestore
.document('newUsers/{userId}')
.onCreate(async (snap, context) => {
    const userId = context.params.userId;
    const newUser = await admin.auth().createUser({
        disabled: false,
        displayName: snap.get('displayName'),
        email: snap.get('email'),
        password: snap.get('password'),
        phoneNumber: snap.get('phoneNumber')
    });
    // You can also store the new user in another collection with extra fields
    await admin.firestore().collection('users').doc(newUser.uid).set({
        uid: newUser.uid,
        email: newUser.email,
        name: newUser.displayName,
        phoneNumber: newUser.phoneNumber,
        otherfield: snap.get('otherfield'),
        anotherfield: snap.get('anotherfield')
    });
    // Delete the temp document
    return admin.firestore().collection('newUsers').doc(userId).delete();
});

您可以使用函数。https.onCall()

exports.createUser= functions.https.onCall((data, context) => {
    const uid = context.auth.uid; // Authorize as you want
    // ... do the same logic as above
});

调用它。

const createUser = firebase.functions().httpsCallable('createUser');
createUser({userData: data}).then(result => {
    // success or error handling
});

答案 3 :(得分:3)

我使用Firebase iOS SDK 在Objective-C中使用André's very clever workaround

NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info" ofType:@"plist"];
FIROptions *secondaryAppOptions = [[FIROptions alloc] initWithContentsOfFile:plistPath];
[FIRApp configureWithName:@"Secondary" options:secondaryAppOptions];
FIRApp *secondaryApp = [FIRApp appNamed:@"Secondary"];
FIRAuth *secondaryAppAuth = [FIRAuth authWithApp:secondaryApp];

[secondaryAppAuth createUserWithEmail:user.email
                             password:user.password
                           completion:^(FIRUser * _Nullable user, NSError * _Nullable error) {
                                [secondaryAppAuth signOut:nil];
                          }];

答案 4 :(得分:1)

Swift 4的更新

我尝试了一些不同的选项,可以从一个帐户创建多个用户,但这是迄今为止最好,最简单的解决方案。

Nico

的原始答案

首先在AppDelegate.swift文件中配置firebase

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    FirebaseApp.configure()
    FirebaseApp.configure(name: "CreatingUsersApp", options: FirebaseApp.app()!.options)

    return true
}

将以下代码添加到您创建帐户的操作中。

            if let secondaryApp = FirebaseApp.app(name: "CreatingUsersApp") {
                let secondaryAppAuth = Auth.auth(app: secondaryApp)

                // Create user in secondary app.
                secondaryAppAuth.createUser(withEmail: email, password: password) { (user, error) in
                    if error != nil {
                        print(error!)
                    } else {
                        //Print created users email.
                        print(user!.email!)

                        //Print current logged in users email.
                        print(Auth.auth().currentUser?.email ?? "default")

                        try! secondaryAppAuth.signOut()

                    }
                }
            }
        }

答案 5 :(得分:1)

这是使用Web SDK的简单解决方案。

  1. 创建云功能(https://firebase.google.com/docs/functions
import admin from 'firebase-admin';
import * as functions from 'firebase-functions';

const createUser = functions.https.onCall((data) => {
  return admin.auth().createUser(data)
    .catch((error) => {
      throw new functions.https.HttpsError('internal', error.message)
    });
});

export default createUser;
  1. 从您的应用中调用此功能
import firebase from 'firebase/app';

const createUser = firebase.functions().httpsCallable('createUser');

createUser({ email, password })
  .then(console.log)
  .catch(console.error);
  1. (可选)您可以使用返回的uid设置用户文档信息。
createUser({ email, password })
  .then(({ data: user }) => {
    return database
      .collection('users')
      .doc(user.uid)
      .set({
        firstname,
        lastname,
        created: new Date(),
      });
  })
  .then(console.log)
  .catch(console.error);

答案 6 :(得分:1)

嘿,我遇到了类似的问题,试图通过管理员创建用户,因为无法在没有登录的情况下注册用户,我创建了一个解决方法,并在下面添加了步骤

  1. 不是注册,而是在 firebase 实时数据库中创建一个以电子邮件为键的节点(firebase 不允许以电子邮件为键,因此我创建了一个函数来从电子邮件生成密钥,反之亦然,我将附加下面的函数)
  2. 在保存用户的同时保存一个初始密码字段(甚至可以使用 bcrypt 或其他东西对其进行哈希处理,如果您愿意,它只会使用一次)
  3. 现在,一旦用户尝试登录,请检查数据库中是否存在具有该电子邮件的任何节点(从电子邮件生成密钥),如果存在,则匹配提供的密码。
  4. 如果密码匹配,则删除节点并使用提供的凭据执行 authSignUpWithEmailandPassword。
  5. 用户注册成功
//Sign In
firebaseDB.child("users").once("value", (snapshot) => {
     const users = snapshot.val();
     const userKey = emailToKey(data.email);
     if (Object.keys(users).find((key) => key === userKey)) {
       setError("user already exist");
       setTimeout(() => {
         setError(false);
       }, 2000);
       setLoading(false);
     } else {
       firebaseDB
         .child(`users`)
         .child(userKey)
         .set({ email: data.email, initPassword: data.password })
         .then(() => setLoading(false))
         .catch(() => {
           setLoading(false);
           setError("Error in creating user please try again");
           setTimeout(() => {
             setError(false);
           }, 2000);
         });
     }
   });

//Sign Up 
signUp = (data, setLoading, setError) => {
 auth
   .createUserWithEmailAndPassword(data.email, data.password)
   .then((res) => {
     const userDetails = {
       email: res.user.email,
       id: res.user.uid,
     };
     const key = emailToKey(data.email);
     app
       .database()
       .ref(`users/${key}`)
       .remove()
       .then(() => {
         firebaseDB.child("users").child(res.user.uid).set(userDetails);
         setLoading(false);
       })
       .catch(() => {
         setLoading(false);
         setError("error while registering try again");
         setTimeout(() => setError(false), 4000);
       });
   })
   .catch((err) => {
     setLoading(false);
     setError(err.message);
     setTimeout(() => setError(false), 4000);
   });
};

//Function to create a valid firebase key from email and vice versa
const emailToKey = (email) => {
 //firebase do not allow ".", "#", "$", "[", or "]"
 let key = email;
 key = key.replace(".", ",0,");
 key = key.replace("#", ",1,");
 key = key.replace("$", ",2,");
 key = key.replace("[", ",3,");
 key = key.replace("]", ",4,");

 return key;
};

const keyToEmail = (key) => {
 let email = key;
 email = email.replace(",0,", ".");
 email = email.replace(",1,", "#");
 email = email.replace(",2,", "$");
 email = email.replace(",3,", "[");
 email = email.replace(",4,", "]");

 return email;
};

答案 7 :(得分:0)

Swift版本:

FIRApp.configure()

// Creating a second app to create user without logging in
FIRApp.configure(withName: "CreatingUsersApp", options: FIRApp.defaultApp()!.options)

if let secondaryApp = FIRApp(named: "CreatingUsersApp") {
    let secondaryAppAuth = FIRAuth(app: secondaryApp)
    secondaryAppAuth?.createUser(...)
}

答案 8 :(得分:0)

这是Jcabrera's answer的Swift 3适应性:

let bundle = Bundle.main
        let path = bundle.path(forResource: "GoogleService-Info", ofType: "plist")!
        let options = FIROptions.init(contentsOfFile: path)
        FIRApp.configure(withName: "Secondary", options: options!)
        let secondary_app = FIRApp.init(named: "Secondary")
        let second_auth = FIRAuth(app : secondary_app!)
        second_auth?.createUser(withEmail: self.username.text!, password: self.password.text!)
        {
            (user,error) in
            print(user!.email!)
            print(FIRAuth.auth()?.currentUser?.email ?? "default")
        }

答案 9 :(得分:0)

如果您使用的是Polymer和Firebase(聚合物火焰),请参阅以下答案:https://stackoverflow.com/a/46698801/1821603

基本上,您创建一个辅助<firebase-app>来处理新用户注册,而不会影响当前用户。

答案 10 :(得分:0)

Android解决方案(科特林):

  1. 您需要FirebaseOptions BUILDER(!)来设置api键,数据库url等,并且不要忘记在最后调用build()
  2. 通过调用FirebaseApp.initializeApp()来创建辅助auth变量
  3. 通过传递您新创建的辅助身份验证来获取FirebaseAuth实例,并执行所需的任何操作(例如createUser)

    // 1. you can find these in your project settings under general tab
    val firebaseOptionsBuilder = FirebaseOptions.Builder()
    firebaseOptionsBuilder.setApiKey("YOUR_API_KEY")
    firebaseOptionsBuilder.setDatabaseUrl("YOUR_DATABASE_URL")
    firebaseOptionsBuilder.setProjectId("YOUR_PROJECT_ID")
    firebaseOptionsBuilder.setApplicationId("YOUR_APPLICATION_ID") //not sure if this one is needed
    val firebaseOptions = firebaseOptionsBuilder.build()
    
    // indeterminate progress dialog *ANKO*
    val progressDialog = indeterminateProgressDialog(resources.getString(R.string.progressDialog_message_registering))
    progressDialog.show()
    
    // 2. second auth created by passing the context, firebase options and a string for secondary db name
    val newAuth = FirebaseApp.initializeApp(this@ListActivity, firebaseOptions, Constants.secondary_db_auth)
    // 3. calling the create method on our newly created auth, passed in getInstance
    FirebaseAuth.getInstance(newAuth).createUserWithEmailAndPassword(email!!, password!!)
            .addOnCompleteListener { it ->
    
                if (it.isSuccessful) {
    
                    // 'it' is a Task<AuthResult>, so we can get our newly created user from result
                    val newUser = it.result.user
    
                    // store wanted values on your user model, e.g. email, name, phonenumber, etc.
                    val user = User()
                    user.email = email
                    user.name = name
                    user.created = Date().time
                    user.active = true
                    user.phone = phone
    
                    // set user model on /db_root/users/uid_of_created_user/, or wherever you want depending on your structure
                    FirebaseDatabase.getInstance().reference.child(Constants.db_users).child(newUser.uid).setValue(user)
    
                    // send newly created user email verification link
                    newUser.sendEmailVerification()
    
                    progressDialog.dismiss()
    
                    // sign him out
                    FirebaseAuth.getInstance(newAuth).signOut()
                    // DELETE SECONDARY AUTH! thanks, Jimmy :D
                    newAuth.delete()
    
                } else {
    
                    progressDialog.dismiss()
    
                    try {
    
                        throw it.exception!!
    
                        // catch exception for already existing user (e-mail)
                    } catch (e: FirebaseAuthUserCollisionException) {
    
                        alert(resources.getString(R.string.exception_FirebaseAuthUserCollision), resources.getString(R.string.alertDialog_title_error)) {
    
                            okButton {
    
                                isCancelable = false
    
                            }
    
                        }.show()
    
                    }
    
                }
    
            }
    

答案 11 :(得分:0)

您可以使用firebase功能添加用户。

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

const cors = require('cors')({
origin: true,
});
exports.AddUser = functions.https.onRequest(( req, res ) => {
// Grab the text parameter.

cors( req, res, ()  => {
    let email  = req.body.email;
    let passwd = req.body.passwd;
    let role   = req.body.role;
    const token = req.get('Authorization').split('Bearer ')[1];

    admin.auth().verifyIdToken(token)
    .then(
            (decoded) => { 
             // return res.status(200).send(  decoded )
             return creatUser(decoded);
            })
    .catch((err) => {
            return res.status(401).send(err) 
     });

    function creatUser(user){
      admin.auth().createUser({
          email: email,
          emailVerified: false,
          password: passwd,
          disabled: false
        })
        .then((result) => {
          console.log('result',result);
           return res.status(200).send(result);
        }).catch((error) => {
           console.log(error.message);
           return res.status(400).send(error.message);
       })
     }

   }); 
 });

答案 12 :(得分:0)

Swift 5:简单解决方案

首先将当前用户存储在名为originalUser的变量中

let originalUser = Auth.auth().currentUser

然后,在创建新用户的完成处理程序中,使用updateCurrentUser方法还原原始用户

Auth.auth().updateCurrentUser(originalUser, completion: nil)

答案 13 :(得分:0)

Android解决方案(JAVA):

没什么,只需将其更改为java并感谢fkvestak提供的Android解决方案作为我的实习任务参考。 https://stackoverflow.com/a/52162643/11726855

FirebaseAuth fba = FirebaseAuth.getInstance();
DatabaseReference dbr = FirebaseDatabase.getInstance().getReference("users");
ProgressDialog pd = new ProgressDialog(this);

public void [ON_CLICK](View view) {
    pd.setMessage("Adding User....");
    pd.show();

    //These can be found in your project settings under General tab
    //Server key under Cloud Messaging tab is not the API key, I've been confused by other posts
    FirebaseOptions.Builder fbo = new FirebaseOptions.Builder();
    fbo.setApiKey("YOUR_WEB_API_KEY");
    fbo.setDatabaseUrl("https://[YOUR_PROJECT_ID].firebaseio.com/");
    fbo.setProjectId("YOUR_PROJECT_ID");
    fbo.setApplicationId("YOUR_APP_ID"); //Tested, App Id is required.
    FirebaseOptions firebaseOptions = fbo.build();
    final FirebaseApp secondaryAuth = FirebaseApp.initializeApp([JAVA_CLASS_NAME].this, firebaseOptions, "secondary_db_auth");

    FirebaseAuth.getInstance(secondaryAuth).createUserWithEmailAndPassword(addUserEmail, addUserPassword)
        .addOnCompleteListener(this,
                new OnCompleteListener<AuthResult>() {
                    @Override
                    public void onComplete(@NonNull Task<AuthResult> task) {
                        pd.dismiss();
                        if (task.isSuccessful()) {
                            //Can inline as "dbr.child(addUserName).setValue(users);", but I don't like the green box
                            String key = addUserName;

                            //Reusable constructor
                            UserFD users = new UserFD(addUserName, addUserPassword, addUserAuthorisation);
                            dbr.child(key).setValue(users);
                            throwSecondaryAuth(secondaryAuth);
                            Toast.makeText(getApplicationContext(),
                                    "Add User Successful", Toast.LENGTH_SHORT).show();
                        } else {
                            //Sorry that still weak in playing with exception, so I use toast                                
                            throwSecondaryAuth(secondaryAuth);
                            Toast.makeText(getApplicationContext(),
                                    "Add User Failed", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
}

Here is the Project Id, API key, and App Id.

And this is the Database URL

让事物可重复使用……

public void throwSecondaryAuth(FirebaseApp secondAuth) {
    FirebaseAuth.getInstance(secondAuth).signOut();
    secondAuth.delete();
}

答案 14 :(得分:0)

在网络上,这是由于在注册上下文之外调用createUserWithEmailAndPassword时发生的意外行为所致;例如通过创建新的用户帐户邀请新用户加入您的应用。

好像,createUserWithEmailAndPassword方法触发一个新的刷新令牌,并且用户cookie也被更新。 (此副作用尚未记录)

这是Web SDK的解决方法: 创建新用户后;

firebase.auth().updateCurrentUser (loggedInUser.current)

前提是您事先用原始用户启动loginInUser。

答案 15 :(得分:0)

如果您想在前端创建第二个身份验证引用,请使用它来创建其他用户并注销并删除该引用。如果您这样做,您将不会在创建新用户时退出登录,也不会收到默认 Firebase 应用已存在的错误消息。

   const createOtherUser =()=>{
            var config = {
                //your firebase config
            };
            let secondaryApp = firebase.initializeApp(config, "secondary");

            secondaryApp.auth().createUserWithEmailAndPassword(email, password).then((userCredential) => {
                console.log(userCredential.user.uid);
            }).then(secondaryApp.auth().signOut()
            )
            .then(secondaryApp.delete()
            )


        }
        

答案 16 :(得分:-3)

我遇到了同样的问题,我用这种方式解决了这个问题:

当用户登录时,我将电子邮件和密码保存在共享首选项中。创建用户后,我再次使用之前保存的电子邮件和密码登录用户。

    String currentEmail = MyApp.getSharedPreferences().getEmail();
    String currentPass = MyApp.getSharedPreferences().getPass();

    FirebaseAuth auth = FirebaseAuth.getInstance();
    auth.createUserWithEmailAndPassword(email, pass)
            .addOnCompleteListener(AddStudent.this, new OnCompleteListener<AuthResult>() {

                @Override
                public void onComplete(@NonNull final Task<AuthResult> task) {

                    if (task.isSuccessful()) {
                        String currentEmail = MyApp.getSharedPreferences().getEmail();
                        String currentPass = MyApp.getSharedPreferences().getPass();

                        //Sign in again
                        auth.signInWithEmailAndPassword(currentEmail, currentPass)
                                .addOnCompleteListener(AddStudent.this, new OnCompleteListener<AuthResult>() {
                                    @Override
                                    public void onComplete(@NonNull Task<AuthResult> task) {
                                        if (!task.isSuccessful()) {
                                            Log.e("RELOGIN", "FAILED");
                                        } else {
                                            Log.e("RELOGIN", "SUCCESS");
                                        }
                                    }
                                });

                        finish();
                    }
                }
    });