Is there a way to only sign in registered users in Firebase Phone Authentication - reactjs

I am building a React app with Firebase Back End that requires the user to register and sign in using their phone number. The problem is that currently, even for a user that does not have an account, once they receive the OTP, they are automatically registered. Is there a way to check if the user is not registered and instead ask them to register rather than sign them in?
My sign in function
const handleSubmit = async (event) => {
event.preventDefault();
if(phone != ''){
setExpanded(true);
generateRecaptcha();
let appVerifier = window.recaptureVerifier;
signInWithPhoneNumber(auth, phone, appVerifier)
.then(confirmationResult => {
window.confirmationResult = confirmationResult;
}).catch((err) => {
console.log(err);
});
}
}
OTP verification:
const verifyOTP = (e) => {
let otp = e.target.value;
setOtp(otp);
if(otp.length === 6) {
console.log(otp);
let confirmationResult = window.confirmationResult;
confirmationResult.confirm(otp).then((result) => {
const user = result.user;
if(user != null){
console.log('Loged');
router.push('/home')
}
}).catch((err) => {
console.log(err);
})
}
}
Kindly help.
Thanks.

SignInWithPhoneNumber method will automatically sign up a new user if the user doesn't exist. There is no way to prevent users from signing up,you can check if the returned user is a new user and if it's new, delete and sign out the user manually.
check the isNewUser property after authentication to check if user logged in for the first time or not.you can refer this link
x.confirm(code)
.then((result) => {
// User signed in successfully.
const { isNewUser } = getAdditionalUserInfo(result)
if (isNewUser) {
// New user - sign up
} else {
// Existing user - log in
}
})
However, you can disable new user sign up with email providers by setting the flag disableSignUp.status to true. This will display an error message when new users attempt to sign up.You can refer this github for more information

Related

Issues with firebase google-Oauth logout in react

I am facing an issue in my React app when implementing Google Auth using Firebase. After a successful login, I need to check if the user exists in my Firebase database. If the user does not exist, I log them out. The issue I am facing is that after logging out, I am unable to sign in again as the authentication popup does not appear. I believe this can be due to caching of the current user in the browser.
Here's my current signInWithGoogle function:
const signInWithGoogle = async () => {
const result = await signInWithPopup(auth, provider);
console.log(result.user)
const mailId = result.user.email ? result.user.email:""
const Isvalid = await validate(mailId);
if (Isvalid) {
console.log('validated user')
navigate('/dashboard')
} else {
signOut(auth).then(() => {
console.log('Signout Successful');
}).catch((err) => {
console.log('Error', err);
})
alert('not a valid user')
}
}

Firebase 9 doesn't remember logged in

I am trying to use firebase 9 auth. I already made sign in and sign up pages. It work correctly.
But I have a problem with remembering the logged in info. I want to remember the user logged info. but it ask me to sign in every time i refresh the page. I tried to check it with onAuthStateChange It sign out every refresh. this is my code for checking:
onAuthStateChanged(auth, () => {
if (user) {
console.log("LOGGED IN");
} else {
console.log("LOGGED OUT");
}
});
It log "LOGGED OUT" every refresh.
The Firebase docs says: You can use this to do remember the logging info
import { getAuth, setPersistence, signInWithEmailAndPassword, browserSessionPersistence } from "firebase/auth";
const auth = getAuth();
setPersistence(auth, browserSessionPersistence)
.then(() => {
// Existing and future Auth states are now persisted in the current
// session only. Closing the window would clear any existing state even
// if a user forgets to sign out.
// ...
// New sign-in will be persisted with session persistence.
return signInWithEmailAndPassword(auth, email, password);
})
.catch((error) => {
// Handle Errors here.
const errorCode = error.code;
const errorMessage = error.message;
});
I tried that this is my code:
useEffect(()=> {
setPersistence(auth, browserLocalPersistence)
.then(() => {
navigate("/");
return signInWithEmailAndPassword(auth, mail, password)
})
.catch((err) => {
console.log(err.message);
pushNotification({ type: "error", message: err.message });
});
}, [])
I tried both of browserLocalPersistence and browserSessionPersistence
Please how can i make remeber logged functionality?
Excuse my english.

FirebaseError: Firebase: Error (auth/invalid-value-(oob-code),-starting-an-object-on-a-scalar-field)

I am getting an error on the oob-code given by firebase, FirebaseError: Firebase: Error (auth/invalid-value-(oob-code),-starting-an-object-on-a-scalar-field)..
This is happening on my reset password function, as I customised my own reset password page instead of using firebase default.
Here are my code, I followed the code on firebase documentation closely but my error comes in at the auth.verifyPasswordResetCode(auth, actionCode).then((email) => { line shown below.
const handleResetPassword = () => {
// Verify the password reset code is valid.
try {
console.log(actionCode)
auth.verifyPasswordResetCode(auth, actionCode).then((email) => {
console.log("got in")
console.log(email)
const accountEmail = email;
// Save the new password.
auth.confirmPasswordReset(auth, actionCode, values.newPassword).then((resp) => {
// Password reset has been confirmed and new password updated.
console.log(resp);
login(accountEmail, values.newPassword)
.then((flag) => {
if (flag.includes('ERROR')) {
setMessage(flag)
}
})
.catch((e) => {
console.log(e);
setMessage("Something went wrong")
})
// TODO: Display a link back to the app, or sign-in the user directly
// if the page belongs to the same domain as the app:
// auth.signInWithEmailAndPassword(accountEmail, newPassword);
// TODO: If a continue URL is available, display a button which on
// click redirects the user back to the app via continueUrl with
// additional state determined from that URL's parameters.
}).catch((error) => {
// Error occurred during confirmation. The code might have expired or the
// password is too weak.
console.log(error)
});
}).catch((error) => {
console.log(error)
// Invalid or expired action code. Ask user to try to reset the password
// again.
});
} catch (e) {
console.log(e);
}
}
Here is the console log output for the error.
Solved!
I used the imported functions instead of the app auth.
import { verifyPasswordResetCode, confirmPasswordReset } from "firebase/auth";
verifyPasswordResetCode(auth, actionCode).then((email) => {
....
confirmPasswordReset(auth, actionCode, values.newPassword).then((resp) => {
...

react native Firebase onAuthStateChanged does not get current user after closing the app while the user its authenticated using social media providers

hello we have the following problem using firebase with react native and social login providers.
The login is not persistent after a successful login using the three major social login providers (google, apple, facebook). The function onAuthStateChanged does not return the user after closing the app while the user logged in using the former providers, therefore the user has to login again every time the app is opened. This problem is not present while using auth with email and password credentials when the app persist user after login and closing the app.
we are using the following technogologies and versions
react-native: 0.63.3
firebase: 8.10.1 (previously we were using 7.8.2 )
react-native-firebase/app": "^14.2.2",
"#react-native-firebase/auth": "^14.2.2"
for creating the credentials we are using the following packages:
#react-native-google-signin/google-signin": "^7.0.3"
#invertase/react-native-apple-authentication": "^2.1.5"
react-native-fbsdk-next": "^6.2.0 -> facebook login
we don't know if it's a problem with firebase because the listener function does not get the user after closing the app with a successful login.
I hope someone can helps us out.
Edit: here is example code how we are using the firebabse and the libraries to login using apple:
on App.js, we have the auth listener
auth.onAuthStateChanged(async (user) => {
try {
if (user) {
const userInfo = await getUserById(user.uid);
const userFetched = userInfo.val();
setUser(userFetched);
}
} catch (error) {
if (error.message !== 'user is null') {
console.log('ERROR: ' + error.message);
}
}
});
login the user and creating the credentials fo
const onAppleButtonPress = async() => {
if (Platform.OS === 'android'){
return onAppleButtonPressAndroid;
}
try {
const appleAuthRequestResponse = await appleAuth.performRequest({
requestedOperation: appleAuth.Operation.LOGIN,
requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME],
});
const {
user: newUser,
email,
nonce,
identityToken,
realUserStatus /* etc */,
} = appleAuthRequestResponse;
if (!identityToken){
Toast.show({
type: 'error',
text1:'error al ingresar con las credenciales',
});
return;
}
// loguear con firebase here
const response = await SignInWithCredentialApple(identityToken,nonce);
const usermail = response.user.email;
const userFound = await searchUserByEmail(usermail);
if (!userFound.exists()){
const newUser = {
uid: response.user.uid,
email: usermail,
role: 'user',
userName: usermail.split('#')[0],
profileFilled: false,
created: new Date(),
authMethod: 'apple',
};
setUser(newUser);
//setUser(newUser);
await addUser(newUser.uid, newUser);
} else {
setUser(Object.values(userFound.val())[0]);
}
} catch (error){
setShowError(true);
if (error.code === appleAuth.Error.CANCELED) {
console.warn('User canceled Apple Sign in.');
setError('Operacion cancelada por el usuario');
} else {
setError(`Error: ${error.toString()}`);
}
}
};
login and creating the credentials
import authRNFirebase from '#react-native-firebase/auth';
export const SignInWithCredentialApple = async (identityToken, nounce) => {
//return auth.signInWithCredential(credential);
const credential = authRNFirebase.AppleAuthProvider.credential(
identityToken,
nounce,
);
return authRNFirebase().signInWithCredential(credential);
};

Error with firebase auth upon sign-up for react app

Whenever I try to sign-up locally, I get this error:
"auth/network-request-failed", message: "A network error (such as timeout, interrupted connection or unreachable host) has occurred."}
Upon sign-up, I'm simply redirecting the user to a new page and that's all.
I read that it could be a problem with the service worker made with create-react-app, but I'm not entirely sure if it's a good idea to disable it.
This is how I'm handling sign-ups:
handleSubmit(e) {
e.preventDefault();
firebase.auth()
.createUserWithEmailAndPassword(this.state.emailValue, this.state.passValue)
.catch((error) => {
console.error(error)
})
this.handleAuthChange()
}
handleAuthChange() {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
window.location = 'thank-you'
let email = user.email
console.log(email + " logged in")
} else {
window.location = ""
console.log("not logged in")
}
})
}
How should I fix this?
Your handleAuthChange() function should probably be called in the success function once sign-in is done considering you want to start the firebase.auth().onAuthStateChanged listener after the firebase.auth().createUserWithEmailAndPassword function call is made.
var self = this;
handleSubmit(e) {
e.preventDefault();
firebase.auth()
.createUserWithEmailAndPassword(this.state.emailValue,
this.state.passValue)
.then(function(userData){
self.handleAuthChange();
})
.catch((error) => {
console.error(error);
})
}
A better idea I guess could be to start the listener on page load by removing it from the function as it will maintain state of the firebase auth is case of page reload.
firebase.auth().onAuthStateChanged((user) => {
if (user) {
window.location = 'thank-you'
let email = user.email
console.log(email + " logged in")
} else {
window.location = ""
console.log("not logged in")
}
});
This listener will automatically detect if a user has logged / signed up into your app using the firebase.auth methods.
Hope this helps.

Resources