Accessing firestore inside createUserWithEmailAndPassword method - javascript

i'm building the app using expo / react native and the firebase javascript web sdk. Could someone take a look at the code below and let me know whether they can figure out why my code isn't working? The code works fine when I'm using expo development mode, and the user profile gets set as expected. However in it's published state it is just not working. The new user is created and logged in, however it doesn't create the user profile.
firebase.auth().signInWithEmailAndPassword(email, password)
.then(user => loginUserSuccess(dispatch, user))
.catch(() => {
firebase.auth().createUserWithEmailAndPassword(email, password)
.then((newUser) => {
var userRef = firebase.firestore().collection("users").doc(newUser.uid);
userRef.set({name: name, email: email, company: company, number: number, user: newUser.uid, adminEmail: '' })
.then(function (){
dispatch({ type: LOGIN_USER_SUCCESS, payload: newUser });
})
.catch(() => loginUserFail(dispatch)
);
})
.catch(() => loginUserFail(dispatch));
I've tried lots of different methods but keep having the same problem. According to the docs, the createUserWithEmailAndPassword method returns the User credentials. I've confirmed this with a debug statement and checked that I am accessing the uid property of said object.
Thanks

Related

React doesn't recognize user attributes in Amplify app

I built an Amplify app with Cognito user pools for authentication/authorization. I am now trying to retrieve user attributes using Auth.currentAuthenticatedUser() . The example code they have (which works well) is the following:
import { Auth } from 'aws-amplify';
Auth.currentAuthenticatedUser({
bypassCache: false
})
.then((user) => console.log(user))
.catch((err) => console.log(err));
Here, the console.log(user) logs all of the current user data, as expected. I would like to now capture that data (or at least individual attributes of it) in a variable that I can use later on. However, if I try to define a variable using user it gives me an undefined error.
Here is an example of what I have tried and the error generated:
Code:
Auth.currentAuthenticatedUser({
bypassCache: false
})
.then((user) => console.log(user))
.catch((err) => console.log(err));
let userData = user;
Error:
'user' is not defined no-undef
I have also tried const and var but no matter what, it does not recognize userĀ . I don't understand how this is possible since it is successfully logged two lines above. Any ideas would be appreciated!
I was able to store the values within a const by putting it inside of a try/catch block:
try {
const user = await Auth.currentAuthenticatedUser();
const userGroup = user;
console.log(user);
} catch (err) {}
In my case, I only wanted the user group, so I actually narrowed it down to that parameter:
const userGroup = user.signInUserSession.accessToken.payload["cognito:groups"]

How do I use Cypress Origin with google accounts?

I am attempting to access a google service embedded into my website which uses accounts.google.com for the login.
I'm trying to use the session/origin commands to do this, but it's failing as if I'm doing nothing at all. I use this with success to login to my application (non google login), but google seems to require something more. I have spent a great deal of time browsing for answers with no luck
Code leading up to login:
cy.get('div [class="active carousel-item"]').find('button').first().click()
cy.loginGoogle(Cypress.env("GoogleUsername"),Cypress.env("GooglePassword"))
Login code:
Cypress.Commands.add('loginGoogle', (username, password) => {
const args = { username, password }
cy.session(args, () =>
{
cy.origin('https://accounts.google.com', { args }, ({ username, password }) => {
cy.visit('https://accounts.google.com/')
cy.get('input[type="email"]').type(username)
cy.get('div[id="identifierNext"]').find('button').click()
cy.get('#login-password').type(password)
cy.get('#btn-login').click()
})
cy.visit('/')
cy.url().should('contain', 'mydomain.com')
})
})
Try to use programmatic authentication as it's suggested in the documentation.

user.emailVerified does not change to 'true' in response to sendEmailVerification link (firebase auth)

someone please help, what am I missing? I send verification email (using firebase sendEmailVerification) succesfully and when I click on the link on the email it does not work, so i end up copying the link and paste in on the browser and hit enter. that way I'm able to get back to my web app and the continue URL does work. This just does not change user.emaiVerified to true.
const user = firebase.auth().currentUser
if(user) {
user.sendEmailVerification(actionCodeSettings)
.then( () => {
console.log("UnpSignUpForm: Verification email sent SUCCESSFULLY");
})
.catch( (error) => {
console.log('UnpSignUpForm: Verification email sending error: ', error)
});
} else {
console.log('no user')
}
I tried using user.reload() in onAuthStateChanged (see below) but I still cannot get user.emailVerified changed to "true".
firebase.auth().onAuthStateChanged( user => {
// console.log('onAuthStateChanged user', user)
if (user) {
console.log('onAuthStateChanged: user is signed IN')
console.log('onAuthStateChanged user', user)
user.reload()
console.log(`user ${user.email} reloaded`)
// User is signed in.
if(user.emailVerified) {
console.log('onAuthStateChanged:email Verified', user.emailVerified)
} else {
console.log('onAuthStateChanged:email NOT Verified', user.emailVerified)
}
} else {
console.log('onAuthStateChanged: onAuthStateChanged: user is signed OUT')
}
});
After the user clicks the link, emailVerified is not automatically updated. It will be updated when the user is reloaded, eg. user.reload().
In addition, the email_verified field in the token claims will be either updated when the token is naturally refreshed after expiration or if you force token refresh after the user email is verified, eg. user.getIdToken(true).
I hope you found out what might have been the problem. I just figured it out. I'm using React.
When you got the email to verify your password, you will have noticed the link looked something like this:
https://yourappname.firebaseapp.com/__/auth/action?mode=verifyEmail&oobCode=p-s8GYqQN9AxuwyVFc7FDe3R3d4O-SIf_6_H4vRMiZtcAAAF3RIT1CA&apiKey=llllllllRLl2LsK842iT9797yHciGBtTuuVVKzs&lang=en
If you inspect the URL, you'll notice 4 parameters:
mode
oobCode
apiKey
lang
When you click on the link, you'll be forwarded to the url you set in your firebase console.
When you access the url in the verification email, you'll need to find a way to parse the query parameters. There's a nice npm package for this called query string which does all the dirty work for you. It also has easy-to-read documentation and I found it easy to implement on React.
Once I parsed the oobCode from the url parameters, I used it as an argument for the following method:
firebase.auth().applyActionCode(<add the oobCode here>)
.then(() => {
// handle success here
}).catch(err => {
//handle failure here
});
For React, I executed the above code in a useEffect hook (for when the page mounts). I can imagine there are similar types of features on Vue and Angular.
As correctly stated above, you can access the new emailVerified property using:
firebase.auth().currentUser.reload().then(() => {
console.log(firebase.auth().currentUser.emailVerified) // should now be 'true'
})

Firebase: Why am I getting Firebase ID Tokens twice?

Question
From the following situations, I could see two different tokens:
After completing the sign-up, I get the first Firebase ID Token.
I'm getting a new JWT when I come back to my app after completely signing out.
What I've found
const app = express();
app.use((req, res, next) => {
if (!req.headers.authorization)
return res.status(403).json({ message: 'Missing Authorization Header' });
const jwt = req.headers.authorization.trim();
return admin.auth().verifyIdToken(jwt).then((decodedToken) => {
const uid = decodedToken.uid; // Exists
const displayName = decodedToken.name; // No displayName, object Undefined
const photoURL = decodedToken.picture; // No photoURL, object Undefined
next();
});
});
Even though I've updated the user's default profile by calling the function below, it seems like ID token does not contain user's displayName and photoURL.
initializeUserProfile(name: string, photoURL: string) {
let data = {
displayName: name,
photoURL: photoURL
};
this.afAuth.auth.currentUser.updateProfile(data).then(() => {
this.getUsersRef(this.currentUserId).update(data); // Save data to firestore
}).catch((err) => console.log(err));
}
Note: After the sign-out and successfully logged into the app, the token's length gets much longer than the previous token. Also, it does contain displayName and photoURL as well.
I've also posted my related issue here, and it seems like the token causes the problem.
Why am I getting a new token? And how can I resolve this issue?
To get a new ID token with the latest claims after you update the profile via updateProfile, you can simply force token refresh by calling: currentUser.getIdToken(true).
Note, naturally on token refresh when the token is expired, the new token will automatically pick up the latest claims with the profile changes. To get this immediately, you can force refresh.

Firebase Auth: updateProfile in Cloud Function?

I tried to use updateProfile() in my Cloud Function, triggered by HTTPS.
Error:
user.updateProfile is not a function
Cloud Function:
app.get("/user/create", (req, res) => {
res.setHeader('Content-Type', 'application/json')
admin.auth().verifyIdToken(req.query.token).then(user => {
let name = req.query.name
user.updateProfile({
displayName: name
}).then(() => {
res.send(JSON.stringify({
result: false,
error: err.message
}))
})
})
})
The error makes totally sense to me, but I've no clue how I can get a actual user reference to update the profile, any idea?
It looks like you're assuming that verifyIdToken() generates a promise that contains a User object. That's not the case here. According to the API docs, it provides a DecodedIdToken object. That object contains a uid property with the UID of the user represented by the token you passed to it.
If you want to get a UserRecord object from there, you can call admin.auth().getUser(uid) with that UID. However, that won't help you update the user's profile.
If you want to update the profile for a given UID, you can call admin.auth().updateUser(uid, properties).

Categories