React + Firebase "sign-in provider disabled" despite it being enabled - javascript

In my Authentication -> Sign-in Method - it's Email & Password set to 'Enabled'.
I have a handler for an onSubmit calling this:
createUser(e){
e.preventDefault();
const email = this.createEmail.value
const password = this.createPassword.value
const confirm = this.confirmPassword.value
if(password === confirm) {
firebase.auth()
.createUserWithEmailAndPassword(email, password)
.then((res) => {
this.showCreate(e)
})
.catch((error) => {
alert(error.message)
})
}
else {
alert('Passwords must match')
}
}
And it shoots this error "The given sign-in provider is disabled for this Firebase project. Enable it in the Firebase console, under the sign-in method tab of the Auth section."
I'm using the firebase npm package. It's a note-taking application and it's successfully communicating with the database.
But I have it Enabled. Is anyone aware of how to fix this, or if there's a setting I seem to be missing?
SOLUTION: I fixed this by removing the environment variable and using the raw API string. Weird.

I fixed this by removing the environment variable and using the raw API string.

Related

Firebase Auth: Unable to update custom claims after setting them with createCustomToken

Details
If you use the function createCustomToken to sign in the user and setting his custom claim, updating the custom claims later using the function setCustomUserClaims will not update the claims even after forcing the idToken to refresh using the function firebase.auth().currentUser.getIdTokenResult(true)
How to reproduce?
Sign in the user on firebase using a custom token generated with the function createCustomToken including the custom claims
firebase.auth().createCustomToken(uid, {myClaim: "test"}).then((customToken) => console.log(customToken))
Sign in the user on the frontend using the custom token
// copy paste the customToken manually for testing
firebase.auth().signInWithCustomToken(customToken)
Update the claim on the backend using setCustomUserClaims
firebase.auth().setCustomUserClaims(uid, {myClaim: "updateTest"})
Refresh the idToken on the frontEnd and log the custom claims
firebase.auth().currentUser
.getIdTokenResult(/*force refresh*/ true)
.then((idTokenResult) => {
console.log(`custom claims`, idTokenResult.claims)
})
You should see that the claim is still { myClaim: "test" } instead of { myClaim: "updateTest" }
Edit: This is actually an intended behavior. The claims set with createCustomToken have a higher priority. The doc mentions it here https://firebase.google.com/docs/auth/admin/custom-claims#set_and_validate_custom_user_claims_via_the_admin_sdk
Setting the custom claims separately at sign in instead of using the function createCustomToken to set them will allow you to edit these claims later.
Working code:
firestore
.doc(`users/${uid}`)
.get()
.then((clientSnapshot) => {
// give user the claims he has
const { permissions = {} } = clientSnapshot.data()
// use setCustomUserClaims to set the claims
return auth.setCustomUserClaims(uid, { permissions })
})
// generate the custom token
// ⚠️ don't use createCustomToken to set permission as you won't be able to update them
.then(() => auth.createCustomToken(uid))
.then((customToken) => {
// send the custom token to the frontend to sign the user in
return res.status(200).json({ customToken })
})

Firebase - check if user created with Google Account is signing up or logging in?

I'm trying to create a web application, where you can log-in and register an account with a google account. I have managed to make it so they can log-in with the signInWithPopup(provider), but not sure how to Implement the sign-up. Any suggestions? or know of any functions in firebase i can use?
There aren't any separate methods to login and sign up when using Google Sign-In or any other provider. If a user with that credential exists then user will be logged in else a new user account will be created. You can then use additionalUserInfo.isNewUser property from the result received from signInWithPopUp method to check if the user is new.
firebase.auth().signInWithPopup(provider).then(function (result) {
const {additionalUserInfo: {isNewUser}} = result;
console.log(isNewUser ? "This user just registered" : "Existing User")
})
For the new Modular SDK (V9.0.0+), the same can be written as:
import { signInWithPopup, getAdditionalUserInfo } from "firebase/auth"
const result = await signInWithPopup(auth, googleProvider);
// Pass the UserCredential
const { isNewUser } = getAdditionalUserInfo(result)
So far, as I understood, you have two options to log in to your website: one is to make a local username/password account on your website, and the other option is to use your google account. I suppose the best way would be to check if the Google account is linked to any existing user using additionalUserInfo.isNewUser, and then linking up your google account with the account that is created via your website locally by following this article: https://firebase.google.com/docs/auth/web/account-linking?hl=lt
Once you have Firebase dependency inside your application. You can use createUserWithEmailAndPassword method to do that.
firebase
.auth()
.createUserWithEmailAndPassword("email#domain.com", "123123")
.then(data => {
data.user.updateProfile({
displayName: this.form.name
}).then(() => {});
})
.catch(err => {
this.error = err.message;
});

Firebase authentication in ReactJS project - user null inside onAuthStateChanged

I'm tearing my hair out trying to setup email/password authentication through firebase.
I've got my firebase configuration setup like so
// Firebase App (the core Firebase SDK) is always required and must be listed first
import firebase from "firebase/app";
//authenticaion module
import "firebase/auth";
// Add the Firebase products that you want to use
import "firebase/firestore";
var firebaseConfig = {
// I've got my api key and other info copied from the console in here
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
export const db = firebase.firestore();
export const app = firebase.auth();
I've got a sign-in form created that calls the following function:
import { app } from "../firebase/firebaseConfig";
const createAccount = () => {
app
.createUserWithEmailAndPassword(email, password)
.then((user) => {
console.log("user created");
console.dir(user);
})
.catch((error) => {
console.log("something went wrong");
});
};
First problem: I'm not seeing the "user created" message, even though I can see the user being created in the Firebase Authentication console. I'm also not seeing the "something went wrong" message that would indicate an exception occurred.
Second problem: I'm trying to do a re-direct when the user signs in. To do this, I've setup a listener on the Firebase auth object as suggested in the docs:
firebase.auth().onAuthStateChanged((user) => {
console.log("Inside listener");
console.dir(user);
});
The problem is, I'm seeing the console message so the function is triggering but 'user' is always null in here even though the user is being created.
Firebase version: 8.2.1
Can anyone see what I'm missing here?
It is normal that in an auth state listener your callback first gets called with null, as that is typically the initial user authentication state as the page is loaded.
Firebase tries to automatically restore the user's authentication state, but this may take some time. Only once the state is restored will it again call your auth state listener with the then active user account.
I found a solution in case anyone runs into a similar issue - the button that was triggering the submit was inside a html form and I was not calling event.preventDefault() and so the page was re-rendering and I believe this was causing the auth callback to work incorrectly. Working code -
const createAccount = (event) => {
event.preventDefault();
app
.createUserWithEmailAndPassword(email, password)
.then((user) => {
console.log("user created");
console.dir(user);
})
.catch((error) => {
console.log("something went wrong");
});
};

Firebase Auth setCustomClaims() not working

I am facing a problem with setting custom claims for Firebase Authentication service's token. I am using Cloud function to set the custom claims for Hasura. The cloud function executes upon new user create event to set the custom claims. Here's my code running in cloud function
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.processSignup = functions.auth.user().onCreate(user => {
// create custom claims for hasura
const hasuraClaims = {
"x-hasura-default-role": "user",
"x-hasura-allowed-roles": ["user"],
"x-hasura-user-id": user.uid
}
// attach claims to user auth object
return admin.auth().setCustomUserClaims(user.uid, hasuraClaims)
.then(_ => {
functions.logger.info('SUCCESS: Custom claims attached');
})
.catch(err => {
console.log('ERROR: ', err);
})
})
In my frontend web page, I am running the following code to get the idToken
// subscribe to user state change
firebase.auth().onAuthStateChanged(async user => {
console.log('Firebase auth state changed');
if (user) {
// User is signed in.
window.User = user;
let idToken = await user.getIdTokenResult();
console.log('idToken: ', idToken);
}
})
I don't know what I'm doing wrong, but the token doesn't contain the custom claims that I've set in my Cloud function processSignup(). I know that the function executed without error because I can check my function logs and find the info entry SUCCESS: Custom claims attached.
Can anyone please help me solve this problem?
Updating claims does not trigger an onAuthStateChanged (the auth state of being logged in or not has not changed, but the users' claims have) and tokens are minted and then used for ~1h.
You are calling getIdTokenResult but not forcing a refresh, try:
let idToken = await user.getIdTokenResult(true);
which will force a new token to be fetched from the server and will (hopefully) include your custom claims.

Amplify w/Cognito: How do I get the Current User's Email?

I am using AWS Amplify, with Cognito for user Auth.
Users go into a user pool, and register and sign in just with email address and password.
When a user that has signed in through Cognito navigates to a certain page, I want to be retrieve their email address. How can I do this?
I am able to retrieve some user data with this code (I am using javascript/Angular):
import Auth from '#aws-amplify/auth';
...
ngOnInit(){
Auth.currentAuthenticatedUser().then((user)=>{
console.log('user = ' + JSON.stringify(user.pool))
})
}
The email does appear on the response, but I haven't yet been able to isolate the email from the returned JSON.
I've tried going through the docs, but I haven't yet found info on stuff like the attribute options I can add to currentAuthenticatedUser(), or if there is another method that is cleaner (which I assume there is).
EDIT: It looks like the following works:
Auth.currentAuthenticatedUser().then((user) => {
console.log('user email = ' + user.attributes.email);
});
But I am still hoping to understand the documentation better. I found this solution in a random github question, not the official docs. Where would I find this solution in the AWS Amplify / Cognito documentation?
import cognito from "../path/to/your/config/cognito.json";
import Amplify, { Auth, Hub } from 'aws-amplify';
...
...
useEffect(() => {
Amplify.configure({ Auth: cognito });
Hub.listen('auth', ({ payload: { event, data } }) => {
switch (event) {
case 'signIn':
console.log('Event name -> ', event, data)
// here is your name, email e.t.c.
console.log(data.signInUserSession.idToken.payload);
break
case 'signOut':
console.log('sign out')
// this.setState({ user: null })
break
default:
console.log('Unhandled use case - ' + event)
}
})
}, [])
You can check this one from the official documentation
and enable read access
General settings -> App clients -> Show details -> Set attribute read and write permissions link
and then to make sure you are fetching the updated attributes
Auth.currentAuthenticatedUser({ bypassCache: true })
Auth.currentSession()
.then((data) => {
// this data has user details in accessToken
}).catch(err => console.log(err));
The following works for me after the user is logged in...
import { Auth, Amplify } from 'aws-amplify'
console.log(Auth.user.attributes.email)

Categories

Resources