Is there any way to get Firebase Auth User UID? - javascript

I am looking to fetch Auth User(s) UID from Firebase via NodeJS or Javascript API.
I have attached screenshot for it so that you will have idea what I am looking for.
Hope, you guys help me out with this.

Auth data is asynchronous in Firebase 3. So you need to wait for the event and then you have access to the current logged in user's UID. You won't be able to get the others. It will get called when the app opens too.
You can also render your app only once receiving the event if you prefer, to avoid extra logic in there to determine if the event has fired yet.
You could also trigger route changes from here based on the presence of user, this combined with a check before loading a route is a solid way to ensure only the right people are viewing publicOnly or privateOnly pages.
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// User logged in already or has just logged in.
console.log(user.uid);
} else {
// User not logged in or has just logged out.
}
});
Within your app you can either save this user object, or get the current user at any time with firebase.auth().currentUser.
https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onAuthStateChanged

if a user is logged in then the console.log will print out:
if (firebase.auth().currentUser !== null)
console.log("user id: " + firebase.auth().currentUser.uid);

on server side you can use firebase admin sdk to get all user information :
const admin = require('firebase-admin')
var serviceAccount = require("./serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://yourprojecturl.firebaseio.com",
});
admin.auth().listUsers().then(data=>{
console.log(data.users)
})

This is an old question but I believe the accepted answer provides a correct answer to a different question; and although the answer from Dipanjan Panja seems to answer the original question, the original poster clarified later in a reply with a different question:
Basically, I need to generate token from UID by Firebase.auth().createCustomToken(UID) to sign in user on firebase with the following function firebase.auth().signInWithCustomToken(token).
Because the original question was clarified that the intent is to use
createCustomToken and signInWithCustomToken, I believe this is a question about using the Firebase Admin SDK or Firebase Functions (both server-side) to provide custom authentication, probably based on a username and password combination, rather than using an email address and password.
I also think there's some confusion over "uid" here, where in the code example below, it does NOT refer to the user's Firebase uid, but rather the uid indicated in the doc for createCustomToken, which shows:
admin
.auth()
.createCustomToken(uid)
.then((customToken) => {
...
In this case, the uid parameter on the createCustomToken call is not the Firebase uid field (which would not yet be known), thus providing a series of frustrating replies to the coder asking this question.
Instead, the uid here refers to any arbitrary basis for logging in for which this custom auth will support. (For example, it could also be an email address, social security number, employee number, anything...)
If you look above that short code block from the documentation page, you'll see that in this case uid was defined as:
const uid = 'some-uid';
Again, this could represent anything that the custom auth wanted it to be, but in this case, let's assume it's username/userid to be paired with a password. So it could have a value of 'admin' or 'appurist' or '123456' or something else.
Answer: So in this case, this particular uid (misnamed) is probably coming from user input, on a login form, which is why it is available at (before) login time. If you know who is trying to log in, some Admin SDK code code then search all users for a matching field (stored on new user registration).
It seems all of this is to get around the fact that Firebase does not support a signInWithUsernameAndPassword (arbitrary userid/username) or even a signInWithUidAndPassword (Firebase UID). So we need Admin SDK workarounds, or Firebase Functions, and the serverless aspect of Firebase is seriously weakened.
For a 6-minute video on the topic of custom auth tokens, I strongly recommend Jen Person's YouTube video for Firebase here:
Minting Custom Tokens with the Admin SDK for Node.js - Firecasts

As of now in Firebase console, there is no direct API to get a list of users, Auth User(s) UID.
But inside your Firebase database, you can maintain the User UID at user level. As below,
"users": {
"user-1": {
"uid": "abcd..",
....
},
"user-2": {
"uid": "abcd..",
....
},
"user-3": {
"uid": "abcd..",
....
}
}
Then you can make a query and retrieve it whenever you need uid's.
Hope this simple solution could help you!

From Firebase docs, use Firebase.getAuth():
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
var authData = ref.getAuth();
if (authData) {
console.log("Authenticated user with uid:", authData.uid);
}
Source:
Firebase.getAuth()

Related

How to add new members in Group using Firebase

I am developing the app which has grouping function.
Now I have the problem about adding new member in group.
Like Slack, in group creating onboarding flow user can decide group name and add members which don't use the app yet.
As adding members function, I want to use inviting mail link using firebase dynamic links.
Data structure is below
User
- id
- name
- email
Group
- id
- groupName
- members[]
Group's members array has user id.
But when someone creates new group, it is possible that new users don't register the app yet.
So they don't have user id property in the app.
How do I fix this problem?
When someone creates new group, should I develop sign up functions new user using Firebase auth? This means then new member has automatically user id, and adding those to members property.
Or should group member array have mail address instead of user id.
Please tell me. I'm happy with Swift or JavaScript you will teach me.
Thank you.
UPDATE
After reading your comment I would propose another approach.
When the Group creator user adds users to a group, if a user does not already exists you could, from the front-end, call a Callable Cloud Function (CF) that creates a temporary Firestore document in a specific collection. The ID of this document will be the (future) userId.
Then, still in this same Cloud Function, you send an email to the email address (you need to generate yourself the email, for example with the email extension) with a link containing the userId as query string value.
Example of code for this first CF:
exports.provisionNewAccount = functions
.https.onCall(async (data, context) => {
try {
// You can check that the caller is authenticated
// if (context.auth.uid) {execute the rest of the code} else {throw an error}
// New user email
const userEmail = data.email;
// Generate the new user docID
const fakeDocRef = admin.firestore().collection('_').doc();
const requestId = fakeDocRef.id;
// Create the doc in a specific collection
await admin.firestore().collection('usersCreationRequests').doc(requestId).set({ email: userEmail, treated: false });
// Generate the link to include in the email
const linkURL = 'https://your.app/register.html?requestId=' + requestId
// Send the email by creating a doc in the Extension collection
await db
.collection("emails")
.add({
to: userEmail,
message: {
subject: "....",
html: `Click to create your account` // adapt the html to add some text
},
});
return {result: 'OK'}
} catch (error) {
console.log(JSON.stringify(error));
throw new functions.https.HttpsError('internal', JSON.stringify(error));
}
});
You call it as explained here, by passing the future user's email.
When the email recipient clicks on the link, you open a specific page of your web app that shows a set of fields for the future user to enter his password, display name etc. Then on clicking on a sign-in button in this page you call a Callable Cloud Function passing it the Firestore document ID plus the field values (you get the document ID from the query string).
As shown below, this Cloud Function creates the user in the Authentication service (using the Admin SDK) and flag the Firestore document as treated. Upon getting back the Cloud Function result in the web app you authenticate the user (you have his email and password, since he/she entered it in the form).
exports.createNewAccount = functions
.https.onCall(async (data, context) => {
try {
const userEmail = data.email;
const userId = data.userId;
const userPassword = data.password;
const userDisplayName = data.displayName;
// Fetch the user doc created in the first CF
const snapshot = await admin.firestore().collection('usersCreationRequests').doc(userId).get();
const treated = snapshot.get('treated');
const email = snapshot.get('email');
if (!treated && userEmail === email) {
const createUserPayload = {
email,
emailVerified: false,
password: userPassword,
displayName: userDisplayName
};
const userRecord = await admin.auth().createUser(createUserPayload);
return { result: 'OK' }
} else {
return { result: 'User already created' }
}
} catch (error) {
console.log(JSON.stringify(error));
throw new functions.https.HttpsError('internal', JSON.stringify(error));
}
});
I’m actually using this exact approach for a B2B collaborative web app in which users can invite new users by email.
INITIAL ANSWER
(Totally different from the update)
So they don't have user id property in the app… How do I fix this
problem? When someone creates new group, should I develop sign up
functions new user using Firebase auth?
You can use the Anonymous Authentication mode, it exactly corresponds to your needs:
You can use Firebase Authentication to create and use temporary
anonymous accounts to authenticate with Firebase. These temporary
anonymous accounts can be used to allow users who haven't yet signed
up to your app to work with data protected by security rules. If an
anonymous user decides to sign up to your app, you can link their
sign-in credentials to the anonymous account so that they can continue
to work with their protected data in future sessions.
When signing-in with Anonymous Authentication a userId (uid) will be created and later you will be able to convert an anonymous account to a permanent account
I always use userId to achive this kind of feature, you can use anonymous authentication to get userId after user click invite link, Then if needed unlock more feature with furter authentication(add more provider).
If you only using mail address without authentication, It's hard to write rules for prevent user access unwanted data, Like anyone knew your email are able to access your account.

How do I set displayName in Firebase when using Apple authentication?

I am trying to use Apple OAuth on the web with the Firebase Javascript SDK, and when I do, the returned user object is fine, except for displayName, which is null.
let provider = new firebase.auth.OAuthProvider("apple.com");
provider.addScope("email");
provider.addScope("name");
let userCred = await firebase.auth().signInWithPopup(provider);
However when I look at the userCred I get:
displayName: null
I tried the scope fullName to no luck.
Is there any way to get the display name? I use it so that my users can see their name on the site, to personalize the experience.
You get this right on the response to appleAuth signin response
const appleAuthRequestResponse = await appleAuth.performRequest({
requestedOperation: appleAuth.Operation.LOGIN,
requestedScopes: [appleAuth.Scope.EMAIL, appleAuth.Scope.FULL_NAME]
});
appleAuthRequestResponse will hold the name details.
Please note that, if you had already used your account for testing, you will have to login to your appleid and remove the apple sign in for your app, to test this.[ Also delete this user from firebase auth ]

What is preferred way to show DOM elements conditioned on firebase authentication

I'm trying to build a small web-page where sign-in is controlled by Firebase Google Auth and is popped up with profile page. What is the secured and preferred way to show the profile page?
Currently I am using onAuthStateChanged to manipulate particular div which holds profile data when user is signed-in. If the user is not logged in I am using removeChild() method to remove that div from DOM and when logged in appendChild() adds back the div.
Supposing you're using firebase's native firebase.auth().onAuthStateChanged function
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
As well as firebase.auth().currentUser to check if the user is currently logged in or not.
In that case, it's perfectly fine to use removeChild and appendChild and they do not hold any security threats, as if a user is not logged, after a page refresh all of the information will vanish.
Here's a small firebase application that shows that when the connection to the firebase is closed and removeChild is used, appendChild stops working as firebase is disconnected, thus proving the point that it's safe to use.
https://jsfiddle.net/vh9xay6e/
Note that in this example I'm not testing any authentification, just the use of firebase with removeChild and appendChild.
You can see that once the connection to Firebase is over, nothing on the frontend side can happen to change that.
Using onAuthStateChanged method we can act upon state change (sign in or Sign out)
As an example :
firebase.auth().onAuthStateChanged(user=>{
if(user){
document.getElementById("id").classList.remove('hide')
//this will populate your class which associate with above id.
} else{
document.getElementById("id_of_your_div").classList.add('hide')
}
})
I think it's okay to use removeChild and appendChild method based on firebase auth state changes in your application.
try to wire around your code by:
var userCurrent = firebase.auth().currentUser; in a function.
NOTE: Make sure you need to be sure first you signed in (as its an async operation), followed by the update user data as:
var authenticationRef = firebase.auth();
authenticationRef.onAuthStateChanged(function(user) {
if (user) {
console.log('onAuthStateChanged : '+user.displayName);
_updateUser();
} else {
console.log('Not login');
}
});
fucntion _updateUser(){
var userCurrent = firebase.auth().currentUser;
userCurrent.updateProfile({
displayName: "Karthik.S",
}).then(function() {
var displayName = userCurrent.displayName;
}, function(error) {
});
}

firebase json db security rule using fb authentication

I am using ionic 3 angular for my mobile app and fb native cordova plugin is used to login.
The firebase db security documentation uses the syntax like
{
"rules":{
"users":{
"$user_id":{
".write":"$user_id === auth.id"
}
}
}
}
the fb authentication looks like below in my app
doLogin(){
if (this.platform.is('cordova')) {
return this.fb.login(['email', 'public_profile']).then(res => {
const facebookCredential = firebase.auth.FacebookAuthProvider.credential(res.authResponse.accessToken);
firebase.auth().signInWithCredential(facebookCredential);
this.navCtrl.setRoot(TabsPage);
})
}
}
my question is the auth firebase variable is taken care with above code or i need to something extra for auth to get required uid etc. ?
The auth firebase variable is token care of in theory: assuming you have the Facebook sign-in method enabled already. However, the database rules you are showing are not necessarily related.
These rules (the same as above):
"rules": {
"users":{
"$variable":{ ".write": "$variable=== auth.uid" }
Dictate that users can only write to a child node with the same uid. I changed $user_id to $variable to highlight that the $ simply denotes a variable that represents the child node's name.
(I should probably mention that it should be auth.uid not auth.id)
This is used to save user specific data. So, when they signup you could have a function that says
firebase.database().ref('users').child(firebase.auth().currentUser.uid).update(<your custom data here>);
*please note how the child of users is the "firebase.auth().currentUser.uid" which can optionally be retrieved from the firebase.auth().signInWithCredential() promise.
Sorry if the explanation was more that necessary. In short. the uid is always present with firebase.auth().currentUser.uid after login and that uid is what the database rules are referring to in auth.uid and last, the auth/uid/etc is pretty much 100% taken care of with firebase.

Firebase - Check Password

I have a scenario that requires checking an entered password against the user's firebase password before the user does an irreversible task. This is different from creating an account or signing in. How can you check against a firebase password? It doesn't look like there's a password property in firebase.auth().currentUser.
Update:
The user must verify their password and the Delete button will run a function to check it. If it matches the firebase password, the Delete button will succeed in triggering a pretty modal to pop up.
I would suggest you to store the user password somewhere if you need to check against it at some point.
Instead of storing it inside your database (which wouldn't be safe) I would personally store it on user's device using UserDefaults so that you can access it easily whenever you need to perform your sensible tasks.
Update:
Another possibility would be using the reauthenticateWithCredential method. If the method return success then, perform your sensitive task. If it fails, ask your user to type the correct password.
As per your request, this is how you would reauthenticate the user using his email & password :
// First you get your current user using Auth :
let currentUser = Auth.auth()?.currentUser
// Then you build up your credential using the current user's current email and password :
let credential = EmailAuthProvider.credential(withEmail: email, password: password)
// use the reauthenticate method using the credential :
currentUser?.reauthenticate(with: credential, completion: { (error) in
guard error == nil else {
return
}
// If there is no error, you're good to go
// ...Do something interesting here
})
You can find some more explanation inside the Firebase documentation here : https://firebase.google.com/docs/auth/ios/manage-users

Categories

Resources