Is it secure to send the user UID to firebase cloud functions - javascript

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

Related

How to add a user’s name when we sign up with fire base auth [duplicate]

I am trying out firebase auth. I want to store a photo-url and a username when the user signs up. My code for signing up -
const email = signupForm['email'].value;
const password = signupForm['password'].value;
auth
.createUserWithEmailAndPassword(email, password)
.then((cred) => {
console.log(cred);
alert('done');
signupForm.reset();
})
.catch((error) => {
console.log(error);
alert(error);
});
Could someone tell me how to add username and photo-url in signup. I know I can make a collection in a firebase db but I read somewhere that username and photo-url can also be saved in firebase auth
Firebase Authentication doesn't have a user property that stores username. You would have to store that on your own, in a database, and make sure the string is unique.
You can store a profile picture URL using updateProfile(). It will not store the image for you - you can only provide a URL. If you need to store the image file itself, tou should probably consider using another product for that, such as Cloud Storage.
Typically, if you have custom information to store per user, you should do that in a database using the unique ID of the user signed in. This gives you full control, rather than depending on what Firebase Auth provides (which is not much). The purpose of Auth is to validate the user's identity, not store per-user information.

Telegraf session for unique user?

I'm building a wallet bot and I was wondering how can I initiate a session for an unique user. For example, in this session I would need an object containing the unique user identifier, the public key and secret key so they can access this after initiating the bot.
I was thinking in something like this:
var myWallet = (ctx) =>{
return{
user: ctx.from.id,
publicKey: wallet.public,
secretKey: wallet.secret
}
}
bot.command('/myWallet', (ctx)=>{
ctx.reply(myWallet.user);
ctx.reply(myWallet.publicKey);
ctx.reply(myWallet.secretKey);
})
But when I type /myWallet on my bot nothing happens, any idea what am I doing wrong?
Might be a bit late but for sessions you can use Telegrafs inbuild session management. Here an example:
const session = require('telegraf/session')
const bot = new Telegraf(process.env.BOT_TOKEN)
bot.use(session())
bot.on('text', (ctx) => {
ctx.session.counter = ctx.session.counter || 0
ctx.session.counter++
return ctx.reply(`Message counter:${ctx.session.counter}`)
})
Basically it just works like above example. You intitiate a session (bot.use(session());) then when a user writes you use the context of the returned message (ctx) in which all user data is stored (username, id, message, etc) and calling the session from that (ctx.session). In there you store your regular variable data. Now normal sesions are active until the bot shuts down. When you want persistent sessions just import an 3rd-party session manager as written in the docs.
So to sum that up:
const session = require('telegraf/session') // import session addon
ctx.session.walletData = 'some data' // store data in session
console.log(ctx.session.walletData) // show data

storing user data in firebase with unique identifiers

I have a publicly accessible app. No sign in is required but I need a way to store user data in the database as an object associated with a unique key.
From what I understand, tokens would be a way to get a unique identifier from firebase(??)
I tried creating an anonymous user and getting a token like this:
let user = firebase.auth().signInAnonymously();
user.getIdToken(true);
I expected getIdToken to return a string but I get an object.
So...
1) Are tokens what I want to do this?
2) If so how can I get a new token as a string?
Use the following code as a global listener on ur page to check if the sign-in is successful:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
var isAnonymous = user.isAnonymous;
var unique_id = user.uid;
} else {
// User is signed out.
// ...
}
});
This snippet has been taken from the Firebase Anonymous Auth link: Click Here to open link.
For some reason I was trying to set up a binding to sync my app with Firebase, which I just realized I don't need at all! (I just need to push the data at the end of the poll).
Of course as soon as removed that requirement it was as simple as:
firebase.database().ref().push().set(myData);
When using the push() method, Firebase automatically generates a unique key which is all I need...

Firebase : Anonymous authentication - How to set identifier?

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.

firebase javascript injection

I want ask something about firebase security. How to handle following situations?
User is creating account with createUserWithEmailAndPassword() function, then i save his username,email,created_at...to realtime db. But what if data are not saved correctly. His account is created and he is logged in automatically but data is not stored.
I have some registration logic... for example unique usernames... so before creating acc i check if this username exist in realtime db. But he still can call createUserWithEmailandPassword() from js console and account is created.
For situation one:
According to the firebase docs (https://www.firebase.com/docs/web/api/firebase/createuser.html), creating a user does not automatically authenticate them. An additional call to authWithPassword() is required first. In order to ensure that a user isn't authenticated without valid data, you could run a check to the server to make sure the data is saved correctly before authenticating.
Edit: Nevermind that; looks like firebase does auto-auth now - take a look at what I wrote below.
Now a concern with this approach would be if your app allowed people to authenticate with an OAuth provider like gmail, then there is no function for creating the user before authenticating them. What you may need to do is pull the user data from the firebase, determine if it's valid, and if its not valid show a popup or redirect that lets the user fix any invalid data.
For situation two:
If you wanted to make sure that in the case of them calling createUserWithEmailAndPassword() from the console a new user is not created, you could try something like this with promises;
var createUserWithEmailAndPassword = function(username, password) {
var promise = isNewUserValid(username, password);
promise.then(function() {
// Code for creating new user goes here
});
}
In this way, you never expose the actual code that makes a new user because it exists within an anonymous function.
I don't think that this could solve the problem entirely though because firebases API would let anyone create an account using something
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
ref.createUser({
email: "bobtony#firebase.com",
password: "correcthorsebatterystaple"
}
(Taken from https://www.firebase.com/docs/web/api/firebase/createuser.html)
If you wanted to make sure that server side you can't ever create a user with the same user name, you'd need to look into firebases's rules, specifically .validate
Using it, you could make sure that the username doesn't already exist in order to validate the operation of creating a username for an account.
Here's the firebase doc on rules: https://www.firebase.com/docs/security/quickstart.html
And this is another question on stack overflow that is quite similar to yours. Enforcing unique usernames with Firebase simplelogin Marein's answer is a good starting point for implementing the server side validation.
First save the user credentials in the realtime database before you create the user:
var rootRef = firebase.database().ref('child');
var newUser = {
[name]: username,
[email]: useremail,
[joined]: date
};
rootRef.update(newUser);
After adding the Usersinfo into the realtime database create a new user:
firebase.auth().createUserWithEmailAndPassword(useremail, userpassword).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
When an error occured while inserting the data in the realtime database, it will skip the createuser function.
This works fine for me, hope this helps!

Categories