Code relevant to the issue
<SimpleButton
onClick={this.onClickLogin}
disabled={!this.isEmailPasswordValid()}
style={{ width: '50%' }}
id="gi-auth-modal-log-in-button">
Log In
</SimpleButton>
async onClickLogin() {
const that = this;
this.props
.loginWithPassword(that.state.email, that.state.password)
.then(() => {
that.props.closeModal();
})
.catch(e => console.log(e))
}
export const loginWithPassword = (email, password) => async (dispatch) => {
return await firebase
.auth()
.signInWithEmailAndPassword(email, password)
.then(async (userData) => {
await dispatch(login(userData));
})
.catch(handleFirebaseError);
};
When I run this project on localhost and try to login (with valid credentials), onClickLogin catches the following error:
{
"code": "auth/invalid-api-key",
"message": "Your API key is invalid, please check you have copied it correctly."
}
The error message seems simple enough but here is the kicker: the same code works in production. My assumption is that since this code works in production but not on localhost it is some kind of environment configuration issue.
Please help me understand what it can be and should there be any differences in login behavior between dev and production (assuming the same DB is used for both).
Firebase code for reference:
import * as firebaseAdmin from 'firebase-admin';
const firebaseConfig = {
apiKey: process.env.FIREBASE_KEY,
projectId: process.env.FIREBASE_PROJECT_ID
};
firebaseAdmin.initializeApp(firebaseConfig);
late answer but I had the same problem.
Do you have any Allow CORS extension installed? Try to toggle it to off and try again.
Make sure you added localhost in the authorized domains list in your firebase project
Related
when create user with Firebase createUserWithEmailAndPassword. Function runs twice. That's why, it gives error that email is already in use. App in vue js 2 and firebase 9.
async registerForm(){
const auth = getAuth()
const user = await createUserWithEmailAndPassword(auth, this.email, this.password)
.then(userCredential => {
this.userId = userCredential.user.uid
console.log(this.userId);
this.x++
})
.catch(error => {
console.log(error);
})
console.log('user signed up', this.x);
this.$router.replace({name: 'home'})**
}
The problem maybe in the routing redirect, if you have located the auth function on the rendering side, when you change the route or move to another one you are rendering again the component which could be a reason to call the function twice
am working on a little project and i did finish all the authentication work but one thing,am wondering how to check if the email is real before going into the process of signup,
by the way am using react and Firebase and i did look online and i did find a package called email-existence i did try it and it dose return true if the email is real and false if the email dosent exist but thats not working when i use it with react it return an error
import firebase from '../util/firebase';
const emailExistence = require('email-existence');
export const normalSignup = (props, setSign, email, password, confirmPassword, username) => {
emailExistence.check(email, function (error, response) { // return error here addresses.sort is not a function
console.log('res: ' + response);
});
}
anyway am wondering if there's a way to do it with Firebase without external packages thanx in advance
PS:am not using cloud functions
Well assuming you want to check if the email is a verified email address you can write the code in the following way
import firebase from '../util/firebase';
const App = {
firebase: firebase,
getLoggedInUser: () => {
const currentUser = App.firebase.auth().currentUser
if (currentUser) {
return {
email: currentUser.email,
userId: currentUser.uid,
isEmailVerified: currentUser.emailVerified
}
} else {
return undefined
}
},
isAuthenticated: () => {
return (App.getLoggedInUser() && App.getLoggedInUser().isEmailVerified)
},
authenticate: async (email, password) => {
await App.firebase.auth().signInWithEmailAndPassword(email, password)
},
signup: async (email, password) => {
const userCredential = await App.firebase.auth().createUserWithEmailAndPassword(email, password)
await userCredential.user.sendEmailVerification()
return `Check your email for verification mail before logging in`
},
Here the following happens
When a user signs up the signup method is called and an email verification is sent by firebase as shown in the above code
When a user logs in the authenticate method is called so according to firebase you are logged in
However to redirect or render a certain page say after log in you can use the isAuthenticated method to display a page to a certain user
So you can pass method isAuthenticated as a prop to react-router and render your web application how you want.
This way only real and authentic email id which are verified will have access to your app
Note
This method is working already in prod but its using VueJS and is an opensource project on github let me know if you want to reference it
Maybe just use a regex to check if the email is valid?
According to this webpage for JavaScript you just need:
const emailRegex = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (emailRegex.test(email)) {
console.log('Email valid!');
}
This won't stop people entering emails for incorrect domains, but ensures that if someone uses a mail server that isn't widely known, it will get accepted too.
Your only option on the client side (if you are on Firebase I suppose you don't have the luxury to run a Node backend) to fetch a similar service as email-existence which returns a "valid" or "invalid" response if you GET the endpoint with the email address.
These are usually premium services, but if you have low traffic you can try out a free one. In my example it is Mailboxlayer.
Their endpoint can be called like this (and of course if you are stick to the client side it means anyone can steal your api key from production via browser network tab!):
GET http://apilayer.net/api/check?access_key=YOUR_ACCESS_KEY&email=richard#example.com
Which returns a JSON:
{
"email": "richard#example.com",
"did_you_mean": "",
"user": "support",
"domain": "apilayer.net",
"format_valid": true,
"mx_found": true,
"smtp_check": true,
"catch_all": false,
"role": true,
"disposable": false,
"free": false,
"score": 0.8
}
Best to use score, which:
[...] returns a numeric score between 0 and 1 reflecting the quality and deliverability of the requested email address.
In React:
const [data, setData] = useState(null)
const [emailToVerify, setEmailToVerify] = useState('richard#example.com') // just for the sake of example
const apiKey = process.env.API_KEY
const fetchEmailVerificationApi = useCallback(async () => {
try {
const response = await fetch(`http://apilayer.net/api/check?access_key=${apiKey}&email=${emailToVerify}`)
const json = await response.json()
setData(json.score) // returns a numeric score between 0 and 1 reflecting the quality and deliverability of the requested email address.
} catch (e) {
console.error(e)
}
}, [apiKey, emailToVerify])
useEffect(() => {
fetchEmailVerificationApi()
}, [fetchEmailVerificationApi])
I am losing my hope at solving a Network Error in my Firebase/React app. The error Uncaught Error: Network Error at auth.esm.js:255 shows up in the console sometimes, and at other times it simply won't show and the user gets logged in with Google successfully.
While searching for an answer, I couldn't find anything conclusive (be it in Stack Overflow or Github issues). The Firebase documentation only shows Thrown if a network error (such as timeout, interrupted connection or unreachable host) has occurred about this.
Below is my piece of code for the log in component.
useEffect(() => {
auth
.getRedirectResult()
.then(function (result) {
if (result.credential) {
const token = result.credential.accessToken
setIdToken(token)
history.push('/')
}
const user = result.user
setUsername(user.displayName)
})
.catch(function (error) {
var errorCode = error.code
var errorMessage = error.message
console.log('errorCode and errorMessage: ', errorCode, errorMessage)
})
}, [])
function handleSignInWithGoogle() {
signInWithGoogle()
setLoading(true)
}
//then, inside of my return statement
<button onClick={() => handleSignInWithGoogle()}> Sign in with Google </button>
And this is what inside of my Firebase file
firebase.initializeApp(firebaseConfig)
export const firestore = firebase.firestore()
export const auth = firebase.auth()
export const provider = new firebase.auth.GoogleAuthProvider()
export const signInWithGoogle = () => auth.signInWithRedirect(provider)
Its possible you have some debugger on the code or any blocking process.
Aparently firebase has a timeout and after that time pass (few seconds on my case) it doesnt allow you, as soon as took out the debugger that was blocking the first start it got solved.
I am trying to configure my firebase settings to that I can send the verifyEmail email from either my development or production environment.
I have a .env file with two settings in it as follows:
REACT_APP_PROD_CONFIRMATION_EMAIL_REDIRECT=https://example.com
REACT_APP_DEV_CONFIRMATION_EMAIL_REDIRECT=http://localhost:3000
Then in my firebase config file I have:
doSendEmailVerification = () =>
this.auth.currentUser.sendEmailVerification({
url: process.env.NODE_ENV === 'production' ? process.env.REACT_APP_PROD_CONFIRMATION_EMAIL_REDIRECT : process.env.REACT_APP_DEV_CONFIRMATION_EMAIL_REDIRECT,
});
This works fine when I'm testing in the development environment.
When I deploy the release and try to test it in production - the email does not send.
Both firebase accounts are configured the same way to send the email.
No error message is generated and the step in my submit handler just gets skipped.
My submit handler has:
this.props.firebase
.doCreateUserWithEmailAndPassword(values.email, values.password)
.then(authUser => {
return this.props.firebase.user(authUser.user.uid).set(
{
name: values.name,
email: values.email,
createdAt: new Date()
},
{ merge: true },
);
})
.then(() => {
return this.props.firebase.doSendEmailVerification();
})
.then(() => {
this.setState({ ...initialValues });
this.props.history.push(ROUTES.DASHBOARD);
You have to whitelist your domains in the Authentication section of firebase for this to work. I've seen several posts on here that say the whitelisting step is no longer required - but for me, it is.
I am trying to change/update a user's email address using :
firebase.auth().changeEmail({oldEmail, newEmail, password}, cb)
But I am getting ...changeEmail is not a function error. I found the reference here from the old firebase docu.
So how to I do it in the 3.x version? Because I cant find a reference in the new documentation.
You're looking for the updateEmail() method on the firebase.User object: https://firebase.google.com/docs/reference/js/firebase.User#updateEmail
Since this is on the user object, your user will already have to be signed in. Hence it only requires the password.
Simple usage:
firebase.auth()
.signInWithEmailAndPassword('you#domain.example', 'correcthorsebatterystaple')
.then(function(userCredential) {
userCredential.user.updateEmail('newyou#domain.example')
})
If someone is looking for updating a user's email via Firebase Admin, it's documented over here and can be performed with:
admin.auth().updateUser(uid, {
email: "modifiedUser#example.com"
});
FOR FIREBASE V9 (modular) USERS:
The accepted answer will not apply to you. Instead, you can do this, i.e., import { updateEmail } and use it like any other import. The following code was copy/pasted directly from the fb docs at https://firebase.google.com/docs/auth/web/manage-users
Happy coding!
import { getAuth, updateEmail } from "firebase/auth";
const auth = getAuth();
updateEmail(auth.currentUser, "user#example.com").then(() => {
// Email updated!
// ...
}).catch((error) => {
// An error occurred
// ...
});
You can do this directly with AngularFire2, you just need to add "currentUser" to your path.
this.af.auth.currentUser.updateEmail(email)
.then(() => {
...
});
You will also need to reauthenticate the login prior to calling this as Firebase requires a fresh authentication to perform certain account functions such as deleting the account, changing the email or the password.
For the project I just implemented this on, I just included the login as part of the change password/email forms and then called "signInWithEmailAndPassword" just prior to the "updateEmail" call.
To update the password just do the following:
this.af.auth.currentUser.updatePassword(password)
.then(() => {
...
});
updateEmail needs to happen right after sign in due to email being a security sensitive info
Example for Kotlin
// need to sign user in immediately before updating the email
auth.signInWithEmailAndPassword("currentEmail","currentPassword")
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
// Sign in success now update email
auth.currentUser!!.updateEmail(newEmail)
.addOnCompleteListener{ task ->
if (task.isSuccessful) {
// email update completed
}else{
// email update failed
}
}
} else {
// sign in failed
}
}
async updateEmail() {
const auth = firebase.auth();
try {
const usercred = await auth.currentUser.updateEmail(this.email.value);
console.log('Email updated!!')
} catch(err) {
console.log(err)
}
}
You can use this to update email with Firebase.
Firebase v9:
const changeEmail = (userInput) => {
const { newEmail, pass } = userInput
signInWithEmailAndPassword(auth, oldEmail, pass)
.then(cred => updateEmail(cred.user, newEmail))
}