Getting null on reset password with Firebase in react native - firebase

I'm getting null in response when hitting password reset function of firebase.
//login with firebase
const ForgotPasswordRequest = async () => {
try {
setIsLoading(true);
const res = await auth().sendPasswordResetEmail(SignupDetails.email); //email is passing
console.log(res); // getting null here
setIsLoading(false);
} catch (error) {
setIsLoading(false);
if (error.code === 'auth/email-already-in-use') {
alert('That email address is already in use!');
}
if (error.code === 'auth/invalid-email') {
alert('That email address is invalid!');
}
if (error.code === 'auth/user-not-found') {
alert('There is no user record with this email!');
}
console.error(error);
}
};
these are the versions i'm using
"#react-native-firebase/app": "^14.2.1",
"#react-native-firebase/auth": "^14.2.1",
Update: This is happening on success response for the email exists in firebase. While on giving wrong email it is authenticating and giving error object.

Related

How to match phone number with the phone number present in firebase real-time database (react-native)

I want to create a login form using firebase authentication in which the only user who is register in our database can login. Here I want to take user phone number from login form and match it with firebase real-time database, if the is present in database then the OTP will send to that phone number otherwise they get a popup message you are not register please register then login.
My database structure is like this,
{
+914587354986
{
name:abc
address:kolkata
email:abc#gmail.com
}
}
I have tried this way, you can see my code
function getData(phoneNumber){
var ref=firebase.app().database('https://phone-otp-verify-17c40-default-rtdb.firebaseio.com/').ref("/user/")
ref.once('value')
.then(snapshot => {
console.log('User data: ', snapshot.val());
})
if((snapshot.val()) == phoneNumber){
signInWithPhoneNumber(phoneNumber);
}else{
alert('number is not register ');
}
}
const signInWithPhoneNumber=async()=> {
try{
const confirmation = await auth().signInWithPhoneNumber(phoneNumber)
setConfirm(confirmation);
alert('Otp send sucessfully');
console.log('Otp send sucessfully');
}catch(error){
alert('Not register');
console.log(' Not register');
}
};
const confirmCode = async()=> {
try {
await confirm.confirm(code);
alert('sucessfull ');
console.log('sucessfull');
navigation.navigate('Home');
} catch (error) {
alert('Invalid code.');
console.log('Invalid code.');
}
};
I was getting error :ReferenceError: Can't find variable: snapshot
image of the error I was getting error image
You are accessing snapshot outside then callback. Move it inside.
function getData(phoneNumber) {
var ref = firebase.app().database('https://phone-otp-verify-17c40-default-rtdb.firebaseio.com/').ref("/user/");
ref.once('value')
.then(snapshot => {
console.log('User data: ', snapshot.val());
if (snapshot.val() == phoneNumber) {
signInWithPhoneNumber(phoneNumber);
} else {
alert('number is not register ');
}
});
}
Just a minor mistake
You are using snapshot.val() outside from scope.
The function should look like this
function getData(phoneNumber) {
var ref = firebase.app().database('https://phone-otp-verify-17c40-default-rtdb.firebaseio.com/').ref("/user/")
ref.once('value')
.then(snapshot => {
console.log('User data: ', snapshot.val());
if ((snapshot.val()) == phoneNumber) {
signInWithPhoneNumber(phoneNumber);
} else {
alert('number is not register ');
}
})
}

missing emails in firebase auth for 20% of facebook credentials

I allow users to login with facebook on my app, backed by firebase authentication.
In around 20% of the facebook logins, I don't receive the user's email. I need the email address in my app, and can't figure out why I don't receive it.
Since I get the email address 80% of the time, I assume I have the right permissions setup to retrieve it.
I also enforced "One account per email address" in firebase-auth, so it seems to be a different issue than that raised in Firebase Auth missing email address.
Relevant extracts of my code:
export const FacebookSignUp: React.FC<SocialAuthProps & { title?: string }> = ({ onError, onSetWaiting, title }) => {
async function onFacebookButtonPress() {
onSetWaiting(true);
const { email, first_name, accessToken } = await getFacebookUserData();
const couldLogin = await tryLoginWithFacebook(email, accessToken);
if (!couldLogin) {
// Create a Firebase credential with the AccessToken
const facebookCredential = FacebookAuthProvider.credential(accessToken);
const userCredential = await firebaseAuth.signInWithCredential(facebookCredential);
if (userCredential.user === null) {
throw new Error("Null user");
}
const signupUser: SignupUserData = {
userId: userCredential.user.uid,
email,
pseudo: first_name || undefined
};
await createSignupUser(signupUser).then(() => {
onSetWaiting(false);
});
}
}
return (
<SocialButton
iconName="facebookIcon"
title={title || "S'inscrire avec Facebook"}
onPress={() =>
onFacebookButtonPress().catch((err) => {
onSetWaiting(false);
if (err instanceof SocialAuthError) {
onError(err);
} else if (err instanceof Error) {
const { message, name, stack } = err;
serverError("Unexpected signup error", { message, name, stack });
}
})
}
/>
);
};
import { LoginManager, AccessToken, GraphRequest, GraphRequestManager } from "react-native-fbsdk";
export async function getFacebookUserData(): Promise<FacebookInfo> {
LoginManager.logOut();
const result = await LoginManager.logInWithPermissions(["public_profile", "email"]);
if (result.isCancelled) {
throw "User cancelled the login process";
}
// Once signed in, get the users AccesToken
const { accessToken } = (await AccessToken.getCurrentAccessToken()) || {};
if (!accessToken) {
throw "Something went wrong obtaining access token";
}
return new Promise((resolve, reject) => {
let req = new GraphRequest(
"/me",
{
httpMethod: "GET",
version: "v2.5",
parameters: {
fields: {
string: "email,first_name"
}
}
},
(err, res) => {
if (err || res === undefined) {
reject(err);
} else {
const { first_name, email } = res as { first_name: string; email: string };
resolve({ first_name, email, accessToken });
}
}
);
new GraphRequestManager().addRequest(req).start();
});
}
Facebook allows you to opt out of passing your email along to third-party apps. You can request it, but the user can deny it.
If I ever log in with Facebook I always opt out of passing my email along - most of the time, the third-party app doesn't need it for legitimate purposes.
"I need the email address in my app" - why? email marketing? account duplication prevention?
In cases where you did not get an email, assume the user has opted-out and/or doesn't have an email tied to their account. If you need one, ask the user to input a contact email address and explain what you are using it for. Expect some users to still opt out and plan around it.
You could always convert their username into a non-existent email like theirusername#noreply.users.yourapp.com depending on your use case.

Expo Google auth cancel causes error instead of returning as cancelled in iOS

I am using Expo 37 with expo-google-app-auth 8.1.0. I am able to sign in users successfully. But in iOS, when a user clicks "cancel", whether in the Alert or the browser window, I get an error:
ERR_APP_AUTH: The operation couldn’t be completed. (org.openid.appauth.general error -3.)
This happens for both the simulator and standalone apps - again only for iOS. Why isn't it just returning an object with "type" : "cancel"?
Implementation of Google login method below:
signInWithGoogle = async (): Promise<void> => {
try {
const result = await Google.logInAsync({
androidClientId: ANDROID_CLIENT_ID,
iosClientId: IOS_CLIENT_ID,
androidStandaloneAppClientId: ANDROID_STANDALONE_CLIENT_ID,
iosStandaloneAppClientId: IOS_STANDALONE_CLIENT_ID,
scopes: ['profile', 'email'],
});
if (result.type === 'success') {
await firebase.auth().setPersistence(firebase.auth.Auth.Persistence.LOCAL);
const credential = firebase.auth.GoogleAuthProvider.credential(result.idToken, result.accessToken);
const googleProfileData = await firebase.auth().signInWithCredential(credential);
if (googleProfileData.user.uid) {
this.props.setShouldBeLoggedOut(false);
this.props.setShouldPerformLogout(false);
} else {
Alert.alert('Unable to sync Google credentials with Authentication server');
}
}
} catch (error) {
Alert.alert('Google Login Error:', error.message);
}
};
If you remove Alert.alert('Google Login Error:', error.message);, App will not crash. I think it might have to do something with error.message?
I ran into the same issue. The best I could do was to check e.code before raising the Alert:
try {
const { type, accessToken } = await Google.logInAsync({
androidClientId: GOOGLE_ANDROID_CLIENT_ID,
androidStandaloneAppClientId: GOOGLE_ANDROID_STANDALONE_CLIENT_ID,
iosClientId: GOOGLE_IOS_CLIENT_ID,
iosStandaloneAppClientId: GOOGLE_IOS_STANDALONE_CLIENT_ID,
});
if (type === "success") {
this._handleAppLogin(accessToken);
}
} catch (e) {
if (e.code != -3) {
Alert.alert("Google Login Error", e.message);
}
}
However, I couldn't find documentation that specified what error codes were possible under what conditions, so this solution might suppress other real errors.

firebase auth return null on signInWithPhoneNumber

I am trying to login with phone number with firebase signInWithPhoneNumber() method for login. In which i have checked whether user auth state has been change or not. If user auth is change then login and redirect to home page. but i m getting auth null
onLoginBtnClicked() {
const { contact, password } = this.props;
const error = Validator('password', password) || Validator('contact', contact);
if (error !== null) {
Alert.alert(error);
} else {
console.log('else');
// this.props.loginUser({ contact, password});
const mobileNo = '+91'+contact;
firebase.auth().signInWithPhoneNumber(mobileNo)
.then(data => console.log(data),
firebase.auth().onAuthStateChanged((user) => {
console.log('user'+user);
if (user && !CurrentUser.isFirstTimeUser) {
const userRef = firebase.database().ref(`/users/`);
userRef.on("value", (snapshot) => {
console.log(snapshot.val());
snapshot.forEach(function(item) {
var itemVal = item.val();
if(itemVal.mobile == contact){
NavigationService.navigate('Home');
}
});
}, (errorObject) => {
console.log("The read failed: " + errorObject.code);
});
//NavigationService.navigate('Home');
}
})
)
.catch(error => console(error.message) );
}
}
There are two things to note here
onAuthStateChanged is a listener which listen for the user auth changes.
signInWithPhoneNumber sends the code to the user's phone, you have to confirm it to authenticate the user.
You need to add the listener in the react lifecycle for the component once it is mounted and remove it when it is unmounted
componentDidMount() {
this.unsubscribe = firebase.auth().onAuthStateChanged((user) => {
if (user) {
this.setState({ user: user.toJSON() });
} else {
// Reset the state since the user has been logged out
}
});
}
componentWillUnmount() {
if (this.unsubscribe) this.unsubscribe();
}
// Send Message here
firebase.auth().signInWithPhoneNumber(mobileNo)
.then(confirmResult => this.setState({ confirmResult })
.catch(error => // handle the error here)
// Authenticate User typed Code here
const { userCode, confirmResult } = this.state;
if (confirmResult && userCode.length > 0) {
confirmResult.confirm(codeInput)
.then((user) => {
// handle user confirmation here or in the listener
})
.catch(error => // handle the error here)
}

Link Multiple Auth Providers to an Account react-native

I'm new with react-native-firebase
I want to link the user after login with facebook provider and google provider
I tried all solutions on the internet but any of them worked.
this is my code
const loginUser = await firebase.auth().signInAndRetrieveDataWithEmailAndPassword('test#gmail.com','password888').then(async function(userRecord) {
console.log("Successfully sign in user:", userRecord.user._user);
let user = firebase.auth().currentUser;
console.log('current user ',user)
let linkAndRetrieveDataWithCredential=firebase.auth().currentUser.linkAndRetrieveDataWithCredential(firebase.auth.FacebookAuthProvider.PROVIDER_ID).then(async u=>{
console.log('linkAndRetrieveDataWithCredential u',u)
}).catch(async (e)=>{
console.log('linkAndRetrieveDataWithCredential error',e)
})
console.log('linkAndRetrieveDataWithCredential error',linkAndRetrieveDataWithCredential)
/**/
await firebase.auth().fetchSignInMethodsForEmail('sss#sss.sss')
.then(async providers => {
console.log('login index providers',providers)
}).catch(function(error){
console.log('login index providers error',error)
})
}).catch(async function(error){
console.log('login error',error,error.email)
if(error.code=='auth/user-not-found'){
}else if(error.code=='auth/wrong-password'){
errorMsg=`${L('password')} ${L('notValid')}`
}
if(errorMsg){
if (Platform.OS === 'android') {
ToastAndroid.show(
errorMsg,
ToastAndroid.LONG
)
} else {
Alert.alert(
'',
errorMsg,
[{ text: L('close'), style: 'cancel' }]
)
}
}
console.log("Error sign in user:", error.code);
})
linkAndRetrieveDataWithCredential needs an AuthCredential, in my app I use react-native-fbsdk to get the credential(You’ll need to follow their setup instructions).
This function will prompt the user to log into his facebook account and return an AccessToken, then you get the credential from firebase and finally linkAndRetrieveDataWithCredential.
linkToFacebook = () => {
LoginManager.logInWithReadPermissions(['public_profile', 'email'])
.then((result) => {
if (result.isCancelled) {
return Promise.reject(new Error('The user cancelled the request'))
}
// Retrieve the access token
return AccessToken.getCurrentAccessToken()
})
.then((data) => {
// Create a new Firebase credential with the token
const credential = firebase.auth.FacebookAuthProvider.credential(data.accessToken)
// Link using the credential
return firebase.auth().currentUser.linkAndRetrieveDataWithCredential(credential)
})
.catch((error) => {
const { code, message } = error
window.alert(message)
})
}

Resources