安全规则无法识别初始 Firebase 登录身份验证

时间:2021-05-13 17:43:23

标签: javascript firebase

我有一个奇怪的问题。我的用户需要先注销然后登录才能在首次注册时正确“触发”Firebase 安全角色。这是流程: 用户向云功能提交详细信息 云功能使用管理员身份验证创建用户并返回响应。 在客户端,当收到响应时,用户使用提供的凭据登录,然后收到需要验证电子邮件的通知。 在他们单击验证链接后,它会刷新客户端,直到它识别出电子邮件已验证。 那时它会调用我的实时数据库,这是拒绝许可的地方。但是,如果他们注销并重新登录,安全规则会正确识别所有内容。这是我的规则:

  "rules": {
        "sendRequests":{
          ".read": false,
            "$requests":{
              ".write": "auth!=null && data.exists()",
            }
        },
        "Notify":{
          ".read":false,
          "$userCardID":{
            ".write": "auth!=null"
          }
        },
        "$users":{
          ".read": "auth != null && auth.token.email_verified===true",
            ".write": "auth.uid === $users",
            ".indexOn":["Name"],
                    "Roster":{
            "$cardID":{
             ".validate": "root.child(auth.uid+'-admin').child('Collection').child(newData.child('ID').val()).exists()" 
            }              
          },
          "Completed":{
            "$cardID":{
             ".validate": "root.child(auth.uid+'-admin').child('Collection').child(newData.child('ID').val()).exists()" 
            }              
          },
          "ToDos":{
            "$cardID":{
             ".validate": "root.child(auth.uid+'-admin').child('Collection').child(newData.child('ID').val()).exists()" 
            }              
          }
        }
      }
}

很好奇这是设计使然还是我在这里遗漏了一步。在电子邮件验证之前,我已检查是否正在创建用户并将数据添加到正确的用户 ID 下的数据库中。

编辑:我还应该提到,在收到来自云功能的响应后,用户使用存储的电子邮件和密码以编程方式登录,他们实际上并没有“单击”登录按钮。不确定这是否会改变什么。

编辑:这是客户端代码:

//This function is trigger when the user clicks on the 'Submit' button on the client form. 
//searchString(username),eml(email),and pwd(password) or all grabbed from the 'input' values of the client form.
//It generates a random 'code' and then submits the data to a firestore doc, this triggers the cloud function to pull the data.

const usersRef = db2.ref();
function createRequest() {
  return new Promise((resolve, reject) => {
    let prefix = "Req"
    let code = prefix;
    for (let it = 0; it < 2; it++) {
      let number = Math.floor(Math.random() * (9999 - 1000) + 1000);
      code = code.concat(number)
      if (it === 1) {
        return resolve(code);
      }
    }
  })
}
createRequest().then((code) => {
  dataStore.collection('NewUserRequests').doc(code).set({
    displayName: searchString,
    email: eml,
    password: pwd,
    ReqID: code
  });
  //Then begin listening for the response ('true' or 'error message'). On 'true' it logs in the user.
  dataStore.collection('NewUserResponses').doc(code).onSnapshot((doc) => {
    log.debug("New user response is: " + doc.data());
    //I have verified on the console this is being received correctly.
    if (doc.data().Response === true) {
      login_user(eml, pwd);
    } else {
      alertNative(doc.data().Response);
    }
  })
});
//the login function for firebase
function login_user(email, pwd) {
  firebase.auth().signInWithEmailAndPassword(email, pwd).then(function(user) {
    newLogin = true;
  }, function(error) {
    log.error("User login error: " + errorMessage);
  });
}
//After login, the firebase auth state change gets triggered:
firebase.auth().onAuthStateChanged((user) => {
if (user) {
    log.info("User Auth Detected")
    //I use the photoURL field to determine if a user is 'new'. I know its not elegant but it works.
    let newNameCheck = firebase.auth().currentUser.photoURL
    if (newNameCheck !== null) {
      if (newNameCheck.indexOf("http://www.example.com/12345678/newUser.png") !== (-1)) {
        createNewUser = true;
        firebase.auth().currentUser.sendEmailVerification().then(function() {
          log.info('Email Verification sent.') // Email sent.
        }).catch(function(error) {
          log.error('There was an issue sending the verification email: ' + error)
        });
      }
    }
    if (user.emailVerified === false) {
      log.warn('This user is not verified!')
      let checkEmail = setInterval(function() {
        firebase.auth().currentUser.reload().then(check => {
            if (firebase.auth().currentUser.emailVerified === true) {
              //FINISH LOGGING IN/BUILDING NEW USER
              clearInterval(checkEmail);
              finishLoginSequence();
            }
           })
        }, 2000)
        } else {
        log.warn('This user is verified!')
        finishLoginSequence()
        }
   }
   //ALL code up to this point triggers normally as expected. When it hits finishLogin Sequence is when permission is denied.
   function finishLoginSequence(){
    log.warn(firebase.auth().currentUser.emailVerified);
    firebase.auth().currentUser.updateProfile({
              photoURL: ""
            }).then(function() {
              log.info('Succesfully update new user profile.')
            }).catch(function(error) {
              log.error('There was an error updating the new user profile: '+error)
            });
    //THIS is approved, and I see the in the console that the profile has been updated.
    currentUser = user.uid;
    log.warn(firebase.auth().currentUser.emailVerified);
    usersRef.child(currentUser+'-admin').child('Collection').once('value',function(snapshot){
        let collection  = snapshot.val()
      fullCollect.push(collection)
      //It never gets here as permission is denied!!
    })
   }
});

日志文件输出

[2021-05-13 19:06:00] Sess7967g4164k [info]  User Auth Detected Caller: lobby.js:1590:11)
[2021-05-13 19:06:00] Sess7967g4164k [warn]  This user is not verified! Caller: lobby.js:1637:13)
[2021-05-13 19:06:00] Sess7967g4164k [info]  Email Verification sent. Caller: lobby.js:1597:17
[2021-05-13 19:06:08] Sess7967g4164k [info]  Email verification has been received. Caller: lobby.js:1642:19
[2021-05-13 19:06:11] Sess7967g4164k [warn]  true Caller: lobby.js:1676:15)
[2021-05-13 19:06:11] Sess7967g4164k [info]  New user detected. Begin building new user account. Caller: lobby.js:1698:17)
[2021-05-13 19:06:11] Sess7967g4164k [warn]  true Caller: lobby.js:1734:17)
[2021-05-13 19:06:11] Sess7967g4164k [error] UnhandledRejection Error: Permission denied
    at https://www.gstatic.com/firebasejs/8.3.2/firebase.js:1:394396 Caller: catchErrors.js:35:15)
[2021-05-13 19:06:12] Sess7967g4164k [info]  Succesfully update new user profile. Caller: lobby.js:1702:19

小提琴测试数据库的规则:

{
  "rules": {
    "UserID999":{
      ".read": "auth != null && auth.token.email_verified===true",
        ".write": "false"
    },
    "UserID888":{
      ".read": "auth != null",
        ".write": "false"
    }
  }
}

0 个答案:

没有答案