How to use multi Auth - firebase? - javascript

I have a register screen that contains "username, email, phone number, Password"
and in this case, I use Phone Number Authentication to verify the number so after user verify his number I save his data into firebase DB,
so after that, I navigate hem to login screen! that should contain Email, Password "he registered by them before"
So I don't just compare if his data exist in DB or not,
So it should be used Email/Password Firebase Auth,
But I think it's will take a lot of hits to my Bill or something,
so what you think to achieve these cases because I'm forced to register by Email For Reset Password later?
here is my register Code
signUp = async () => {
const {phoneNumber} = this.state;
this.setState({message: 'code was sent'});
const phoneWithAreaCode = phoneNumber.replace(/^0+/, '+972');
console.log(phoneWithAreaCode);
auth()
.signInWithPhoneNumber(phoneWithAreaCode, true)
.then(confirmResult => {
console.log('confirmResult', confirmResult);
this.setState({confirmResult, message: 'code was sent'});
// this.createUserDatabase();
})
.then(() => {
this.props.navigation.navigate('Confirmation', {
message: this.state.message,
confirmResult: this.state.confirmResult,
createUser: uid => this.createUserDatabase(uid),
phoneWithAreaCode: phoneWithAreaCode,
signInPhoneNumber: phone => auth().signInWithPhoneNumber(phone),
});
});
};
createUserDatabase = uid => {
const {userName, phoneNumber, email} = this.state;
// const uid = auth().currentUser.uid;
const data = {
uid,
name: userName,
email: email,
phoneNumber: phoneNumber,
};
database()
.ref(`users/${uid}`)
.set(data)
.then(() => {
console.log('New poll data sent!');
})
.catch(error => console.log('Error when creating new poll.', error));
};

Related

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

select action occurs befor insert postgresql

im dealing with a problem i can't solve. I've got 2 tables - 'users' and 'login'. The 'users' table keep all my user's info and the 'login' table keep the user's emails and hashes:
this is my backend code:
const handleRegister = (req, res, db, bcrypt, saltRounds) => {
const { email, first_name, last_name, password } = req.body;
// creating hash for password
const salt = bcrypt.genSaltSync(saltRounds);
const hash = bcrypt.hashSync(password, salt);
// form validation
if ( !email || !first_name || !last_name || !password) {
return res.status(400).json('incorrect form submission');
}
// updating login and users tables in the database
db.transaction(trx => {
trx.insert({
first_name: first_name,
last_name: last_name,
email: email,
joined: new Date()
})
.into('users')
.returning('email')
.then(loginEmail => {
return trx('login')
.returning('email')
.insert ({
hash: hash,
email: loginEmail[0]
})
.then(userEmail => {
db.select('*').from('users').where('email', userEmail[0])
.then(user => {
userInfo = Object.assign(user[0], {lists: []} , {tasks: []});
res.json({user: userInfo});
})
.catch(err => {res.status(400).json('unable to get user')})
})
})
.then(trx.commit)
.catch(trx.rollback)
})
.catch(err => {
res.status(400).json('unable to register');
console.log(err);
})
At first when i try to add new user through postman everything is ok, but when i try to add another user i got an error: "TypeError: Cannot convert undefined or null to object" because for some reason the db.select in line 28 does not get any result and passes user=[]. The thing is that when i check my database - the user that i just added is there. it looks like its doing the db.select in line 28 before the insert in line 23...
thank you for your help.

How can I set a user's display name and email with Firebase signInWithCredentials()

I am writing a login / signup page for my React Native app, and I am using Firebase's signInWithCredential() function.
As you can see in the code below, I pass a credential and if the response shows it's a new user, I append to my database, otherwise I sent them to the home screen.
await firebase
.auth()
.signInWithCredential(credential)
.then((response) => {
if (response.additionalUserInfo.isNewUser) {
setShowVerifier(false);
setShowRegistration(true);
// append data to database if user is new
const data = { firstName, lastName, email, phoneNumber };
db.collection("users")
.doc(response.user.uid)
.set(data)
.then(() => {
setShowPhoneNumber(true);
setShowVerifier(false);
setShowRegistration(false);
navigation.navigate("Home");
}).catch(() => {
alert("Error creating account, try again");
});
} else {
setShowVerifier(false);
setShowPhoneNumber(true);
// set verification code to empty string
setVerificationCode("");
navigation.navigate("Home");
}
});
When I find out that the user is in fact a new user, how would I go about updating that user's Firebase auth information, like their displayName and email? (shown below in JSON response)
"user": Object {
"displayName": null,
"email": null,
"emailVerified": false,
"isAnonymous": false,
"lastLoginAt": "1603914278694",
"photoURL": null,
}
Added this chunk of code to the code chunk found above.
auth.currentUser.updateProfile({
displayName: firstName + " " + lastName,
email: email,
});
Updated code chunk:
await firebase
.auth()
.signInWithCredential(credential)
.then((response) => {
if (response.additionalUserInfo.isNewUser) {
setShowVerifier(false);
setShowRegistration(true);
// append data to database if user is new
const data = { firstName, lastName, email, phoneNumber };
db.collection("users")
.doc(response.user.uid)
.set(data)
.then(() => {
setShowPhoneNumber(true);
setShowVerifier(false);
setShowRegistration(false);
navigation.navigate("Home");
}).catch(() => {
alert("Error creating account, try again");
});
} else {
setShowVerifier(false);
setShowPhoneNumber(true);
// set verification code to empty string
setVerificationCode("");
navigation.navigate("Home");
}
});

How To Fix "Unknown error status: Error: The uid must be a non-empty string with at most 128 characters." in Firebase Functions

I'm trying to create a user in my firebase app by passing the data from the UI to a callable function where I
create a user account using email password then
add a display name then create a profile in a user collection then
send a user confirmation email but I get the error
Unknown error status: Error: The uid must be a non-empty string with at most 128 characters.
at new HttpsError (/srv/node_modules/firebase-functions/lib/providers/https.js:102:19)
at admin.auth.createUser.then.then.then.catch.error (/srv/index.js:41:12)
at <anonymous>
const db = admin.firestore();
exports.createUser = functions.https.onCall((data,context)=>{
return admin.auth().createUser({
email: data.email,
password: data.password,
displayName: data.displayName,
}).then(user =>{
return db.doc('users/'+user.uid).set({
email: data.email,
displayName:data.displayName,
type:data.type,
organization:data.organization
});
})
.then(user=>{
let uid = user.uid;
if (data.type === "admin"){
return admin.auth().setCustomUserClaims(uid,{
isAdmin: true,
})
}else{
return admin.auth().setCustomUserClaims(uid,{
isAdmin: false,
})
}
})
.then(user =>{
return user.sendEmailVerification();
})
.catch(error =>{
new functions.https.HttpsError(error);
});
})
and this is my code on my React JS front end
let createUser = functions.httpsCallable('createUser')
createUser({
email: this.state.email,
password: this.state.password,
displayName:this.state.name,
type:this.state.type,
organization:this.state.organization
})
.then(result => {
console.log(result)
})
.catch(error => {
console.log(error)
})
When you do
return db.doc('users/'+user.uid).set({
email: ....});
})
.then(user => { // here, user is undefined})
the value of user (i.e. the fulfillment value, or, in other words, the argument you pass to the first callback function you pass to the then method) is undefined since the set() method returns a "non-null Promise containing void".
You need to save the value of uid in a variable in the previous then(), as shown in the code below.
Note also that, by doing,
.then(user =>{
return user.sendEmailVerification();
})
firstly you get the same problem than above (the value of user is undefined), but, in addition, in the Admin SDK there isn't a sendEmailVerification() method, which is a method of the client JavaScript SDK.
You can use the generateEmailVerificationLink() method of the Admin SDK and send the link by email (from the Cloud Function) to the user, through Sendgrid for example.
const db = admin.firestore();
exports.createUser = functions.https.onCall((data,context)=>{
let userUid;
return admin.auth().createUser({
email: data.email,
password: data.password,
displayName: data.displayName,
}).then(user =>{
userUid = user.uid;
return db.doc('users/'+userUid).set({
email: data.email,
displayName:data.displayName,
type:data.type,
organization:data.organization
});
})
.then(()=>{
if (data.type === "admin"){
return admin.auth().setCustomUserClaims(userUid,{
isAdmin: true,
})
}else{
return admin.auth().setCustomUserClaims(userUid,{
isAdmin: false,
})
}
})
.then(() =>{
//You may use the generateEmailVerificationLink() method, see
//https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#generateEmailVerificationLink
const actionCodeSettings = ....
return admin.auth()
.generateEmailVerificationLink(data.email, actionCodeSettings)
})
.then(link => {
//The link was successfully generated.
//Send an email to the user through an email service
//See https://github.com/firebase/functions-samples/tree/master/email-confirmation
//or https://stackoverflow.com/questions/50205390/send-transactional-email-with-sendgrid-in-cloud-functions-firebase/50248871
})
.catch(error =>{
throw new functions.https.HttpsError('unknown', error.message);
});
})

Create user with firebase admin sdk that can signIn using email and password

I'm using firebase admin SDK on cloud functions to create users using
admin.auth().createUser({
email: someEmail,
password: somePassword,
})
now I want user to signIn using signInWithEmailAndPassword('someEmail', 'somePassword') but I cannot.
I get the following error
{code: "auth/user-not-found", message: "There is no user record corresponding to this identifier. The user may have been deleted."}
There doesn't seem to be a reason to Stringify/Parse. This worked after I struggled with an unrelated typo...
FUNCTION CALL FROM REACT JS BUTTON CLICK
<Button onClick={() => {
var data = {
"email": "name#example.com",
"emailVerified": true,
"phoneNumber": "+15551212",
"password": "randomPW",
"displayName": "User Name",
"disabled": false,
"sponsor": "Extra Payload #1 (optional)",
"study": "Extra Payload #2 (optional)"
};
var createUser = firebase.functions().httpsCallable('createUser');
createUser( data ).then(function (result) {
// Read result of the Cloud Function.
console.log(result.data)
});
}}>Create User</Button>
And in the index.js in your /functions subdirectory:
const functions = require("firebase-functions");
const admin = require('firebase-admin');
admin.initializeApp();
// CREATE NEW USER IN FIREBASE BY FUNCTION
exports.createUser = functions.https.onCall(async (data, context) => {
try {
const user = await admin.auth().createUser({
email: data.email,
emailVerified: true,
password: data.password,
displayName: data.displayName,
disabled: false,
});
return {
response: user
};
} catch (error) {
throw new functions.https.HttpsError('failed to create a user');
}
});
Screen shot of console output
In 2022 there still is no method built into the Admin SDK that would allow to create users in the emulator.
What you can do is to use the REST API of the emulator to create users there directly. The API is documented here: https://firebase.google.com/docs/reference/rest/auth#section-create-email-password
Provided you have got and nanoid installed you can use the following code to create users in the emulator.
import { nanoid } from 'nanoid'
import httpClientFor from '../lib/http-client/client.js'
const httpClient = httpClientFor('POST')
export const createTestUser = async ({ email = `test-${nanoid(5)}#example.io`, password = nanoid(10), displayName = 'Tony' } = {}) => {
const key = nanoid(31)
const { body: responseBody } = await httpClient(`http://localhost:9099/identitytoolkit.googleapis.com/v1/accounts:signUp?key=${key}`, {
json: {
email,
password,
displayName
}
})
const responseObject = JSON.parse(responseBody)
const { localId: userId, email: userEmail, idToken, refreshToken } = responseObject
return { userId, userEmail, idToken, refreshToken }
}
Please note: As there is no error handling implemented, this snippet is not suitable for production use.
Try like that
And please be ensure that user is created from the panel
admin.auth().createUser({
email: "user#example.com",
emailVerified: false,
phoneNumber: "+11234567890",
password: "secretPassword",
displayName: "John Doe",
photoURL: "http://www.example.com/12345678/photo.png",
disabled: false
})
.then(function(userRecord) {
// See the UserRecord reference doc for the contents of userRecord.
console.log("Successfully created new user:", userRecord.uid);
})
.catch(function(error) {
console.log("Error creating new user:", error);
});
Just in case anyone else comes across this I was able to fix it with the help of this.
Here is a working example inside of an onCreate cloud function:
exports.newProjectLead = functions.firestore
.document('newProjectForms/{docId}')
.onCreate(async (snapshot) => {
const docId = snapshot.id
// this is what fixed it the issue
// stringify the data
const data = JSON.stringify(snapshot.data())
// then parse it back to JSON
const obj = JSON.parse(data)
console.log(obj)
const email = obj.contactEmail
console.log(email)
const password = 'ChangeMe123'
const response = await admin.auth().createUser({
email,
password
})
data
const uid = response.uid
const dbRef = admin.firestore().collection(`clients`)
await dbRef.doc(docId).set({
id: docId,
...data,
uid
}, {
merge: true
})
console.log('New Client Created')
})

Categories

Resources