I have a firestore collection and every user has one document. The document name is equal to the user UID.
I write to these documents with a firebase function. So I pass the user UID to this firebase cloud function so the function can write to the database (this is just a very simple write so I won't show it here).
Here is the function call in my js file:
const saveAllTimeData = firebase.functions().httpsCallable('saveAllTimeData');
saveAllTimeData({ data: firebase.auth().currentUser.uid })
But I am not very sure if this is safe.
Can't just someone change the firebase.auth().currentUser.uid part before the execution? And f.e. put in another uid to change documents he shouldn't be able to change?
The user's UID is safe to share as a UID acts like a fingerprint to differentiate and identify a user from another. these do not in any way give permission or power over that user, it is simply a random set of characters that is unique.
With the Admin SDK, you are also able to create these UID's per design, allowing you to have a custom UID that may represent their username if so desired.
Since you are also using a httpsCallable cloud function, this includes a value called context, which uses the JWT token from the auth module. the JWT token is decodable to the user and should not be shared. however, the method httpsCallable secures it through the HTTPS tunnel making it secure from most hijacking.
in your function, you should notice the context variable
exports.addMessage = functions.https.onCall((data, context) => {
// ...
});
For onCall, context contains a property called auth of which contains the decoded JWT values
// Message text passed from the client.
const text = data.text;
// Authentication / user information is automatically added to the request.
const uid = context.auth.uid;
const name = context.auth.token.name || null;
const picture = context.auth.token.picture || null;
const email = context.auth.token.email || null;
references
https://firebase.google.com/docs/reference/functions/providers_https_#oncall
https://firebase.google.com/docs/reference/functions/providers_https_.callablecontext
https://firebase.google.com/docs/auth/admin/verify-id-tokens
I'm currently trying to integrate Stripe with my Firebase's Cloud Firestore db through using Cloud Functions for Firebase. The onCreate trigger is happening correctly but I also want it to update or set a specific field called "customer_id" into the right document in my Users collection. I think something is a little off about how I write my function since I'm not the most experienced with javascript.
I've also tried
return admin.firestore().ref(`Users/${user.uid}/customer_id`).set(customer.id);
'use strict';
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
//const logging = require('#google-cloud/logging')();
const stripe = require('stripe')(functions.config().stripe.token);
const currency = functions.config().stripe.currency || 'USD';
// When a user is created, register them with Stripe
exports.createStripeCustomer = functions.auth.user().onCreate((user) => {
return stripe.customers.create({
email: user.email,
}).then((customer) => {
return admin.firestore().collection("Users").doc(user.uid).update({"customer_id": customer.id})
});
});
Customer gets created with Stripe no problem but the "customter_id" field is not getting updated on the Firestore db.
Print screen of the database:
Print screen of the error log:
As said in the comments, from the print screen of the error log, the code you have deployed does not correspond to the code you are referencing to in your question.
The code in your question looks correct.
I am trying to add a registration page for users to register on a firebase database in a web page(it's wordpress).
For example when I create the user and then try a simple console log to check the created user's uid like so:
auth.createUserWithEmailAndPassword(email, password)
.then(function(user){
console.log(user.uid);
});
I get an "undefined". But when I attempt to do the same thing by typing
auth.createUserWithEmailAndPassword(email, password)
.then(function(user){
console.log(user.user.uid);
});
It works correctly.
Why is this?
I followed the documentation for initialising firebase and then set the reference to the auth as
var auth = firebase.auth();
Thanks for any help. I am new to both Javascript and Firebase.
From the documentation
createUserWithEmailAndPassword(email, password) returns firebase.Promise containing non-null firebase.auth.UserCredential
Clicking firebase.auth.UserCredential shows you it has the structure
{
user: nullable firebase.User,
credential: nullable firebase.auth.AuthCredential,
operationType: (nullable string or undefined),
additionalUserInfo: (nullable firebase.auth.AdditionalUserInfo or undefined)
}
So you are accessing the user property of the returned UserCredential object which you have named user.
If you wanted to, you could change user to userCredential to help clarify what it is and avoid future confusion.
auth.createUserWithEmailAndPassword(email, password)
.then(function(userCredential){
console.log(userCredential.user.uid);
});
const promise = firebase.auth().signInAnonymously();
This is the code i use to create anonymous authentication.
I get the name of the visitor and i have to store
const user_id = response.uid;
const userPromise = firebase.database().ref('users/' + user_id).set({
username: this.state.name
});
response.uid is received from promise.
Again, when the user visits the site again
firebase.auth().onAuthStateChanged(user => {
I have to grab uid first, i need to use the firebase api to fetch the username.
Is it possible to store username in identifier column?
A good place to store the user name is in the display name field of the Firebase Authentication profile. You can read this with firebase.auth().currentUser.displayName and set it through updateProfile.
The (unclear) example in the new docs:
var user = firebase.auth().currentUser;
var credential;
// Prompt the user to re-provide their sign-in credentials
user.reauthenticateWithCredential(credential).then(function() {
How should I create this credential object?
I tried:
reauthenticateWithCredential(email, password) (like the login method)
reauthenticateWithCredential({ email, password }) (the docs mention one argument only)
No luck :(
PS: I don't count the hours wasted searching for relevant info in the new docs... I miss so much the fabulous firebase.com docs, but wanted to switch to v3 or superior for firebase.storage...
I managed to make it work, docs should be updated to include this for who does not want to spend too much time in the exhaustive-but-hard-to-read API reference.
Firebase 8.x
The credential object is created like so:
const user = firebase.auth().currentUser;
const credential = firebase.auth.EmailAuthProvider.credential(
user.email,
userProvidedPassword
);
// Now you can use that to reauthenticate
user.reauthenticateWithCredential(credential);
Firebase 9.x
(Thanks #Dako Junior for his answer that I'm adding here for exhaustivity)
import {
EmailAuthProvider,
getAuth,
reauthenticateWithCredential,
} from 'firebase/auth'
const auth = getAuth()
const credential = EmailAuthProvider.credential(
auth.currentUser.email,
userProvidedPassword
)
const result = await reauthenticateWithCredential(
auth.currentUser,
credential
)
// User successfully reauthenticated. New ID tokens should be valid.
Note
Some people asked about userProvidedPassword, if it was some sort of stored variable from the first login. It is not, you should open a new dialog/page with a password input, and the user will enter their password again.
I insist that you must not try to workaround it by storing user password in cleartext. This is a normal feature for an app. In GMail for example, sometimes your session expires, or there is a suspicion of hack, you change location, etc. GMail asks for your password again. This is reauthentication.
It won't happen often but an app using Firebase should support it or the user will be stuck at some point.
Complete answer - you can use the following:
var user = firebase.auth().currentUser;
var credentials = firebase.auth.EmailAuthProvider.credential(
user.email,
'yourpassword'
);
user.reauthenticateWithCredential(credentials);
Please note that reauthenticateWithCredential is the updated version of reauthenticate()
There are multiple methods to re-authenticat. See the refs: https://firebase.google.com/docs/reference/js/firebase.User
firebase
.auth()
.currentUser.reauthenticateWithPopup(new firebase.auth.GoogleAuthProvider())
.then((UserCredential) => {
console.log("re-outh", UserCredential);
});
In case your app allows multiple authentication methods you might want to first find out what privider was used. You can do this by looking at the firebase.auth().currentUser.providerData array.
With the new firebase version 9.*
import {
EmailAuthProvider,
getAuth,
reauthenticateWithCredential,
} from "firebase/auth";
const auth = getAuth();
let credential = EmailAuthProvider.credential(
auth.currentUser.email,
password
);
reauthenticateWithCredential(auth.currentUser, credential)
.then(result => {
// User successfully reauthenticated. New ID tokens should be valid.
})
I agree that the documentation is not pretty clear on this. But looking a little deeper on the API reference I found firebase.auth.AuthCredential and this and I guess you should be looking to pass it to reauthenticate().
I'm guessing here but I would start trying to log the firebase.auth() to see if there is any credential object there.
I suppose it will look something like the following:
user.reauthenticate(firebase.auth().credential).then(function() {
Now there's a small change in the method since both posted answers are deprecated,
val user = auth.currentUser
user?.let { _user ->
val credentials = EmailAuthProvider.getCredential(
_user.email!!,
"userPassword"
)
_user.reauthenticate(credentials).addOnCompleteListener { _reauthenticateTask ->
}
final FirebaseUser fireBaseUser = FirebaseAuth.getInstance().getCurrentUser();
AuthCredential credential = EmailAuthProvider.getCredential(fireBaseUser.getEmail(), storedPassword);
fireBaseUser.reauthenticate(credential).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> reAuthenticateTask) {
if (!reAuthenticateTask.isSuccessful())
...
}
});