Can I call function in previous screen - react native? - javascript

I have a function "signInWithPhoneNumber" in SignUp screen after call it navigates me to a Confirmation Screen and I pass some params after navigate to confirm a verification code I was received,
So in this screen "Confirmation", I have a button "Re-send Verification Code" so my question is
when I press to "re-send" I want to call a "signInWithPhoneNumber" function in SignUp screen to get a new code
So what you think? that's possible?
Or rewrite a signInWithPhoneNumber in a confirmation screen and call it after pressed re-send button?
SignUp Screen - Function
signUp = async () => {
const {phoneNumber} = this.state;
this.setState({message: 'Sending code ...'});
const phoneWithAreaCode = phoneNumber.replace(/^0+/, '+972');
console.log(phoneWithAreaCode);
auth()
.signInWithPhoneNumber(phoneWithAreaCode, true)
.then(confirmResult => {
console.log('confirmResult', confirmResult);
this.setState({confirmResult, message: 'Code has been sent!'});
// this.createUserDatabase();
})
.then(() => {
this.props.navigation.navigate('Confirmation', {
message: this.state.message,
confirmResult: this.state.confirmResult,
createUser: uid => this.createUserDatabase(uid),
});
});
};
Confirmation screen - function
confirmCode = codeInput => {
const confirmResult = this.props.navigation.state.params.confirmResult
if (confirmResult && codeInput.length) {
confirmResult
.confirm(codeInput)
.then(user => {
clearInterval(this.interval);
const {params} = this.props.navigation.state;
//Check if any users exist
database()
.ref(`users`)
.limitToFirst(1)
.once('value', snapshot => {
if (snapshot.exists()) {
console.log('exists!');
return true;
} else {
params.createUser(user.uid);
console.log('No user found Hah');
}
});
this.setState({
timer: 0,
message: 'Code Confirmed!',
isValid: true,
});
})
.catch(error => {
let errorCode = error.code;
let errorMessage = error.message;
console.log(errorCode);
switch (errorCode) {
case 'auth/invalid-verification-code':
this.setState({message: 'Code is invalid', codeInput: ''});
this.refs.codeInputRef2.clear();
break;
default:
alert(`Please, Check your Messages!`);
break;
}
console.log(errorMessage);
});
} else {
console.log('Not here');
}
};

You can send signInWithPhoneNumber to Confirmation screen, while navigating to it from SignUp screen, like so
this.props.navigation.navigate('Confirmation', {
message: this.state.message,
confirmResult: this.state.confirmResult,
createUser: uid => this.createUserDatabase(uid),
signInWithPhoneNumber: signInWithPhoneNumber // your actual function here
});
});
And then this function will be available in Confirmation screen as a prop, and you can call it when necessary

Related

Firebase Auth- Not adding users after signup

I am trying to add users with email and password function in Firebase but the information is not added once the sign up button is clicked. I have inserted the block of code I've written to perform this action. I'm not sure what I'm missing.The user information does not appear in the console and there is no error message. All other data that is entered works, the authentication part is the only thing that is not working correctly.
// signing new users up
const signupForm = document.querySelector('.signup');
signupForm.addEventListener('submit', (e) => {
e.preventDefault();
const email = signupForm.email.value;
const password = signupForm.password.value;
createUserWithEmailAndPassword(auth, email, password)
.then((cred) => {
// console.log('user created:', cred.user);
signupForm.reset();
})
.catch((err) => {
// console.log(err.message);
});
// logging in and out
const logoutButton = document.querySelector('.logout');
logoutButton.addEventListener('click', () => {
signOut(auth)
.then(() => {
alert('user signed out');
})
.catch((err) => {
console.log(err.message);
});
});
const loginForm = document.querySelector('.login');
loginForm.addEventListener('submit', (e) => {
e.preventDefault();
const email = loginForm.email.value;
const password = loginForm.password.value;
signInWithEmailAndPassword(auth, email, password)
.then((cred) => {
console.log('user logged in:', cred.user);
loginForm.reset();
})
.catch((err) => {
console.log(err.message);
});```

How to prevent function inside another function to refresh my form details?

I have a function that is supposed to submit card details to Stripe.
The stripe.confirmCardPayment is inside handleSubmit and while debugging I realized that my form details clears whenever an await function is called ( tokenize() or confirmCardPayment() )
How can I prevent that ?
edit: I created a myTest() and called it with await inside handleSubmit and it's not refreshing the form at all. I'm completely lost !
function myTest(){
return 'hey'
}
The handleSubmit function:
//Submit payment to Stripe and handle error
const handleSubmit = async(e) => {
e.preventDefault();
console.log('CheckoutHandleSubmit');
//verify instance and token is there
if(!stripe || !elements || !token || !data){
console.log('return !')
return
}
//Get CardElement and attach to DOM
const cardElement = elements.getElement(CardElement);
cardElement.mount('#card-element');
debugger
//console.log('creating payment intent');
//console.log('myData:', data);
//console.log('beforeTokenizing:');
//Tokenize card details and handle errors
try{
const unTest = await myTest(); // => returns 'hey', do not refresh form
const payload = await stripe.confirmCardPayment(
data.info.clientSecret,
{
payment_method: {
card: cardElement,
//billing_details: { name: formData.lastnameInput },
},
}
)
//console.log('payload:', payload)
}catch(err){
console.log('err:', err)
}
const tokenize = await swell.payment.tokenize({
card: {
onError: (err) => {
//inform the customer there was an error
if(err){
console.log('error:', err);
}
//setProcessing(false);
},
onSuccess: async() => {
//submit the form
}
}
})
};

User object is getting populated but Auth.currentSession is returning "No user found"

When the user clicks on the "sign-in" button and if user.challangeName === 'NEW_PASSWORD_REQUIRED'is true, I redirect the user to a page (form screen) where he can provide the input for required attributes and a new password. Even tho the user object is getting populated upon clicking on the sign-in button, using Auth.currentsession on the form screen will print "No user found"
Can someone let me know why I'm seeing no user? What am I doing wrong here?
Here's my login function (triggered when clicked on sign-in button) where I direct the user to the change password screen (form screen) if user.challangeName === 'NEW_PASSWORD_REQUIRED' is true.
const login = async (email, password) => {
try {
const user = await Auth.signIn(email, password);
if (user.challengeName === 'NEW_PASSWORD_REQUIRED') {
navigate('/change-password');
return;
}
if (user) {
setToken(user.signInUserSession.idToken.jwtToken);
const userDetails = await getAccountDetails();
dispatch({
type: LOGIN,
payload: {
user: {
attributes: user.attributes,
username: user.username
},
client: userDetails
}
});
}
} catch (error) {
await logout();
throw error;
}
};
Here's my onSubmit function on the change password screen where eventually I want to use Auth.completeNewPassword to update the user's password in Cognito
const onSubmitClick = (e) => {
e.preventDefault();
if (validateFields());
Auth.currentSession()
.then((user) => console.log(user))
.catch((err) => console.log(err));
};
Here's the documentation provided by AWS https://docs.amplify.aws/lib/auth/manageusers/q/platform/js/#forgot-password, and the code provided by AWS to update password
Auth.signIn(username, password)
.then(user => {
if (user.challengeName === 'NEW_PASSWORD_REQUIRED') {
const { requiredAttributes } = user.challengeParam; // the array of required attributes, e.g ['email', 'phone_number']
Auth.completeNewPassword(
user, // the Cognito User Object
newPassword, // the new password
// OPTIONAL, the required attributes
{
email: 'xxxx#example.com',
phone_number: '1234567890'
}
).then(user => {
// at this time the user is logged in if no MFA required
console.log(user);
}).catch(e => {
console.log(e);
});
} else {
// other situations
}
}).catch(e => {
console.log(e);
});
New updated answer to reflect your updated post, change the onSubmitClick to the following:
const onSubmitClick = (e) => {
e.preventDefault();
if (validateFields());
Auth.currentAuthenticatedUser()
.then(user => {
console.log(user))
})
.then((data) => console.log(data))
.catch((err) => console.log(err));
};
You are looking at the documentation which shows how to use the user after Auth.signIn() (which was my previous answer), compared to what you use: Auth.currentAuthenticatedUser(). The proper documentation example you have to look at is this one: https://www.docs.amplify.aws/lib/auth/manageusers/q/platform/js

Firebase custom user claims are not set

I am trying to add custom user claims after user sign up, to define user role, using setCustomUserClaims:
/api/users/addUser.js
export default async (req, res) => {
const { displayName, email, password, role } = req.body;
if (!displayName || !password || !email || !role) {
return res.status(400).send({ message: 'Missing fields' });
}
try {
const { uid } = await admin.auth().createUser({
displayName,
email,
password,
});
await admin.auth().setCustomUserClaims(uid, role);
res.status(201).send(uid);
} catch (error) {
handleError(res, error);
}
};
This code checks for any change in the authentication state and sets user to the currently logged in user:
/utils/use-auth.js
useEffect(() => {
const unsubscribe = firebase.auth().onAuthStateChanged((user) => {
if (user) {
setUser(user);
} else {
setUser(false);
// Router.push('/login');
}
});
in my /pages/user/home,jsx:
import { useAuth } from '../../utils/use-auth';
function home() {
const { user } = useAuth();
return (
<div>
<pre>{JSON.stringify(user, null, 4)}</pre>
<AdminLayout componentProps={{ selected: '1' }} Component={HomeContent} />
</div>
);
}
The displayed object doesn't have any custom claims.
when I check the firebase console, I find that the user is actually added.
Try using
admin.auth().setCustomUserClaims(uid, claims).then(() => {
// Do your stuff here
});
And verify the claims like
admin.auth().verifyIdToken(idToken).then((claims) => {
// check claims
if (claims) {
// do your stuff here
}
});
for more info check https://firebase.google.com/docs/auth/admin/custom-claims#node.js

How to use email and phone to authentication in Firebase?

I am looking for a way in react-native to make user sign up with his phone number then add his email and password.
But when a user logs in, he logs in only with email and password.
The phone number is only for security reasons.
I do a signInWithPhoneNumber() after user verify his number i call a createUserWithEmailAndPassword() but that's made in console Auth Two separate authentication in the same time
"Email" & "Phone Number"
code
// I just pass the result into separate screen then use it to confirm all stuff is work :D
...
auth()
.signInWithPhoneNumber(phoneWithAreaCode, true)
.then(confirmResult => {
console.log('2', phoneWithAreaCode);
console.log('confirmResult', confirmResult);
this.setState({
confirmResult,
loading: false,
});
})
...
confirmCode = codeInput => {
const {confirmResult, email, password} = this.state;
console.log('codeInput Is:', codeInput.length);
if (confirmResult && codeInput.length) {
confirmResult
.confirm(codeInput)
.then(async () => {
clearInterval(this.interval);
const {params} = this.props.navigation.state;
await auth()
.createUserWithEmailAndPassword(email, password)
.then(({user}) => {
console.log('hey u');
let uid = user.uid;
params.createUser(uid);
})
.catch(error => {
// Handle Errors here.
var errorCode = error.code;
switch (errorCode) {
case 'auth/email-already-in-use':
this.setState({loading: false, password: ''});
break;
case 'auth/invalid-email':
this.setState({loading: false, password: ''});
break;
case 'auth/operation-not-allowed':
this.setState({loading: false, password: ''});
break;
case 'auth/weak-password':
this.setState({loading: false, password: ''});
break;
default:
this.setState({loading: false, password: ''});
break;
}
});
//Check if any users exist
// database()
// .ref(`users`)
// .limitToFirst(1)
// .once('value', async snapshot => {
// if (snapshot.exists()) {
// console.log('exists!');
// return true;
// } else {
// // params.createUser(user.uid);
// console.log('No user found Hah');
// }
// });
this.setState({
timer: 0,
isValid: true,
});
})
.catch(error => {
let errorCode = error.code;
let errorMessage = error.message;
console.log(errorCode);
switch (errorCode) {
case 'auth/invalid-verification-code':
this.setState({codeInput: ''});
this.refs.codeInputRef2.clear();
break;
default:
break;
}
console.log(errorMessage);
});
} else {
console.log('Not here');
}
};
EDIT
confirmCode = codeInput => {
const {confirmResult, password, email} = this.state;
console.log('codeInput Is:', codeInput.length);
if (confirmResult && codeInput.length) {
confirmResult
.confirm(codeInput)
.then(user => {
console.log(user);
let userE = auth().currentUser;
// userE.updateEmail(email);
auth().createUserWithEmailAndPassword(email, password);
clearInterval(this.interval);
const {params} = this.props.navigation.state;
params.createUser(user.uid);
this.setState({
timer: 0,
isValid: true,
});
})
.catch(error => {
let errorCode = error.code;
let errorMessage = error.message;
switch (errorCode) {
case 'auth/invalid-verification-code':
this.refs.codeInputRef2.clear();
break;
default:
break;
}
console.log(errorMessage);
});
} else {
console.log('Not here');
}
};
If you want to use multiple auth providers for the same user, then you need to link them to prevent creating separate users. To link them you can use linkWithCredential() for example:
var credential = firebase.auth.EmailAuthProvider.credential(email, password);
Here you pass the email and password to the EmailAuthProvider.credential method, then you can pass the AuthCredential object to the signed-in user's linkWithCredential method:
firebase.auth().currentUser.linkWithCredential(credential).then(function(usercred) {
var user = usercred.user;
console.log("Account linking success", user);
}, function(error) {
console.log("Account linking error", error);
});
You can check the docs for other ways to link multiple providers :
https://firebase.google.com/docs/auth/web/account-linking
https://firebase.google.com/docs/auth/web/account-linking#link-email-address-and-password-credentials-to-a-user-account

Categories

Resources