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.
Related
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 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.
When a user is authenticated I trigger a cloud Firestore Cloud Function below;
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase)
exports.createUserAccount = functions.auth.user().onCreate((user) => {
const uid = user.uid
const firstName = user.firstName
const familyName = user.familyName
const displayName = user.displayName
const email = user.email
const photoURL = user.photoURL
const newUser = admin.firestore().doc(`/users/${uid}`)
return newUser.set({
firstName: firstName,
familyName: familyName,
displayName: displayName,
email: email,
photoURL: photoURL,
})
})
I run into an issue when a user is logged in anonymously. I have tried adding a const isAnonymous = user.isAnonymous and then returning it under;
return newUser.set({
isAnonymous: isAnonymous,
ERROR LOG IN CONSOLE
Error: Value for argument "data" is not a valid Firestore document. Cannot use "undefined" as a Firestore value (found in field isAnonymous).
My question is how do I check if the user is anonymously logged in or not through a Firebase Cloud Function?
The UserRecord object delivered to your auth function will never have an isAnonymous property on it. That's why it's always taking the value undefined. Check the link to the API documentation to see what's there. I'm not sure how you came to the conclusion that it should be there.
Each authentication provider that has verified an account is present in the providerData array property of the UserRecord object. You should look through that array to check if it's an anonymous account. Specifically, you should be checking the providerId field of each UserInfo object in the providerData array. I'm not 100% certain if this is the correct approach, but from what I'm observing, an anonymous account will have an empty providerData array, since it's not been verified by any auth providers.
As long as you are using email-based authentication (email+pass & OAuth) then you can simply check
if (user.email !== null){
// Run this code if the user is not anonymous
}
Docs
As far as I know there is no direct API for checking if a user is anonymous using the firebase admin sdk. By checking that a user has been active and don't have any connected login providers I believe it should work however.
const user = await admin.auth().getUser('Bp7DmEl5HKcDKrQr7QFVnQXS8FH1')
const hasBeenActive = user.metadata.lastSignInTime != null
const hasProviders = user.providerData.length > 0
const isAnonymous = hasBeenActive && !hasProviders
Note that the reason for the active check is to filter out users who are created manually using either the firebase console or with the admin sdk. Depending on your use case you might want to consider them anonymous as well.
I want to add Google, Facebook and custom login to my Angular7 web app.
Is the UID identifier given by each provider unique ? I mean, can I use it as a user ID in my users Firestore collection ?
And if that's the case, can I still use the createId() method to generate this ID myself in my custom login ? Or might it be the same as one of the providers UIDs ?
Yes you can use it as an UID in your users collection.
Here is my authentification flow:
1/ User creates a new account with email/password
async signUpWithPassword(email, password) {
await firebase.auth().createUserWithEmailAndPassword(email, password)
// user created!
}
2/ I run a cloud function with the auth's onCreate triggers to save the user to my collection:
export const createUserProfile = functions.auth
.user()
.onCreate((user: admin.auth.UserRecord) => {
const { uid } = user
const userRef = db.doc(`users/${uid}`)
// Save it to firestore
return userRef.set({ points: 200 })
})
3/ If this user tries to register with another provider (Google/Facebook etc.), I detect if he's using the same email address, if so I link the new provider to the current one via account linking:
https://firebase.google.com/docs/auth/web/account-linking
That way, the user is going to have multiple auth providers attached to one unique UID/profile.
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