电话认证用户的Firebase重新认证和电子邮件链接

时间:2019-11-11 23:59:30

标签: node.js firebase react-native firebase-authentication react-native-firebase

用户注册后,他们使用电话验证。在使用该应用一段时间后,建议他们将(电子邮件和密码)链接到其现有帐户。

由于该错误,链接过程失败(auth / requires-recent-login。)。我的代码如下。

// The following generates the error: [auth/requires-recent-login] This operation is sensitive and requires recent authentication. Log in again before retrying this request.
const emailCredential = firebase.auth.EmailAuthProvider.credential(state.email, state.password);

const newCredential = await firebase.auth().currentUser.linkWithCredential(emailCredential); 

要解决此错误,我知道在链接之前需要调用reauthenticateWithCredential()。但是,我不想让用户再次登录(接收并输入验证码。)完全可以吗?

我尝试将currentUser.getIdToken(true)的结果传递给PhoneAuthProvider.credential(),但不确定是否正确。无论如何,它都会产生一个错误(如果没有verifyProof,sessionInfo,临时证明或注册ID,则无法创建PhoneAuthCredntial。)。

我的代码如下。

// The following works: 
const accessToken = await firebase.auth().currentUser.getIdToken(true); 

// The following works: 
const currentCredential = firebase.auth.PhoneAuthProvider.credential(accessToken); 

// The following generates the error: Cannot create PhoneAuthCredential without either verificationProof, sessionInfo, temporary proof, or enrollment ID.
const abc = await firebase.auth().currentUser.reauthenticateWithCredential(currentCredential); 

// The following is never reached:  
const emailCredential = firebase.auth.EmailAuthProvider.credential(state.email, state.password);

const newCredential = await firebase.auth().currentUser.linkWithCredential(emailCredential); 

谢谢您的努力和时间来帮助我...

1 个答案:

答案 0 :(得分:0)

重要信息:

  1. firebase.auth()。currentUser.reauthenticateWithCredential(凭据)需要属性凭据
  2. 对于使用电话号码登录的用户,我找不到需要时获得此证书的方法。顺便说一句,可以为登录的用户获取此证书。使用其他提供商,例如脸书
  3. 但是,对于使用电话号码登录的用户,可以在登录过程中获得此凭据。选中https://firebase.google.com/docs/auth/web/phone-auth
  4. 因此,我决定在登录过程中将用户的凭据保存在他们的设备上。我为此使用Redux和Redux-Persist。

我的代码修复后。

// This is an extract from the login script: 
firebase.auth().signInWithPhoneNumber(phoneNo)
    .then(confirmResult => {
        dispatch({ type: "PhoneNo_accepted", payload: { confirmResult: confirmResult } }); 
    })
    .catch(error => { 
        dispatch({ type: "display_message", payload: { messageText: `Phone Number Error: ${error.message}` } });
    });

// Change#1. The following statement is a NEW step, which I added to get the credential during the login process. 
const credential = firebase.auth.PhoneAuthProvider.credential(state.confirmResult.verificationId, state.codeInput);

state.confirmResult.confirm(state.codeInput)
    .then( (user) => {
        // Change#2. The following function would save the credential to the app's state, e.g. using Redux
        _onAuthComplete(user, credential);
    })
    .catch( error => { 
        dispatch({ type: "display_message", payload: { messageText: `Verification Code Error: ${error.message}` } });
    });

// // // 

// This is an extract from the linking script: 
// Change#3. props.credential is the credential, which was saved to the app's state. 
await firebase.auth().currentUser.reauthenticateWithCredential(props.credential);

const emailCredential = firebase.auth.EmailAuthProvider.credential(state.email, state.password);
const newCredential = await firebase.auth().currentUser.linkWithCredential(emailCredential);