Parse - why does user.getSessionToken() return undefined - javascript

I'm using cloud function to fetch user's sessionToken. The documentation says, this method only returns correct value when a user object is fetched with the master key. However, even if I use the master key, I still get the undefined result. What's wrong with my code?
Parse.Cloud.define("hello", function(request, response) {
Parse.Cloud.useMasterKey();
Parse.Promise.as().then(function(){
var query = new Parse.Query(Parse.User);
return query.first({useMasterKey:true});
}).then(function(user){
return user.fetch({useMasterKey:true});
}).then(function(user){
response.success(user.getSessionToken());
});
});

That won't work because the user is not logged in when you fetch him via cloud code. For getSessionToken to work you need to already have a logged in user. Because, otherwise how would CloudCode know which session of your user you want to get? (if he is logged in multiple devices) Also your code is returning the first user in the database, is that realy what you want?
Either way, you need to log the user in via cloud code and then return the session token. However I had some trouble doing that without the password (just by calling user.logIn(), it should work so give it a try) so the only solution I found was to change the password of the user and then log him in. Why do you need to fetch the user's session token? If you don't mind changing the user's password you can do something like:
var password; //create new random passowrd
query.first({useMasterKey: true}).then(function(user){
user.set("password", password);
return user.save();
}).then(function(user){
return Parse.User.logIn(user.get("username"), password);
}).then(function(user){
return user.getSessionToken();
});

Related

PasswordCredential does not store the data

I'm using the PasswordCredential API in Google Chrome and Edge to store authentication credentials, however this data is not saved.
I'm using the code below, and I only fire it if my AJAX login is successful.
var cred = new PasswordCredential({
name: account,
id: email,
password: password,
iconURL: 'https://example.com/favicon.ico'
});
navigator.credentials.store(cred).then(() => {
if (redirect !== undefined) {
$window.location.href = 'dashboard.html';
}
});
If inside the then function of the .store I put it to pull the saved data, null data is displayed.
navigator.credentials.store(cred).then(() => {
navigator.credentials.get({ password: true }).then(function (auth) {
console.log(auth); //Return NULL
console.log(auth.password); //Returns that does not exist
console.log(auth.id); //Returns that does not exist
console.log(auth.name); //Returns that does not exist
});
});
What did I do wrong in my code?
Edit
I believe I found the problem, as the user chooses and not saving the credentials in the browser the promise is pending.
Is there any way to do this automatically without the user having to manually save?
And how do I handle the promise when it completes?
As per W3C it store api will return the promise to make sure it has raised proper request to browser or not, it will not tell if use save or not. If you want to achieve this, you may create setInterval where you can regularly check by calling get from store.
In Reference to save, promise already shows fulfilled as below:

firebase auth applyActionCode method does not turn emailVerified to true

I am developing firebase authentication system where a user is sent email to verify email adr. I got everything working eventually. The user signs up and the email (with the link) is sent to the signed up edmail adr. I use custom email action handler (https://firebase.google.com/docs/auth/custom-email-handler) to respond to a click on the link. On my node.js express route, I get oobCode (which firebase documentation say is "A one-time code, used to identify and verify a request") and pass it as an argument to firebase.auth().applyActionCode(oobCode) which returns a void promise when resolved. see code below.
firebase.auth().applyActionCode(oobCode)
.then( () => {
return admin.auth().updateUser(currentUser.uid, {
emailVerified: true,
})
})
.then( () => {
return res.status(301).redirect(`../unps/${currentUser.uid}`)
})
.catch( (error) => {
return res.status(500).json({ unp_error: `error message: ${error.message} - error code:
${error.code}` })
});
My undestanding of the documentation is that, applyActionCode method, if resolved, will set the emailVerified to true but this does not happen even though there is no error. I had to call updateUser to change emailVerified to true. Shouldnt this be done automatically by the method applyActionCode if a valid oobCode is presented as argument? What am I missinmg? Pleaase help?
All information about the Firebase Authentication user in your application code is taken from the ID token. This ID token is valid for an hour, and automatically refreshed by the SDK about 5 minutes before it expires. Until the token is refreshed, it may not reflect the latest value of emailVerified or other information about that user profile on the server.
It is indeed normal that you need to force a refresh of the token, to get the updated status before it auto-refreshes. When you do that, you shouldn't have to call admin.auth().updateUser(...) though.

Passport.js, Express session Cross-browser with same credentials

I've written code with Passport.js for authentication purpose. While user logged into chrome and using same credentials user logged into another browser 'FF'.
As we all know that Passport.js store all details into req.users and req.session.passport.users. If from one browser user update some details how can we update into another browsers req object without logout?
Same kind of, If admin update user1 details and he already logged in than how that will affect?
Any clue?
As we all know that Passport.js store all details into req.users and
Not necessarily. passport.js does not store user details in req.user, but your passport.js integration code loads the user details from some backend storage and then puts it in the request object on every request.
So it is up to you to update the user in the backend and decide when to retrieve a new version ( instead of just deserializing jwt, for example ) on every request just as well.
Sample code from http://www.passportjs.org/docs/basic-digest/
passport.use(new BasicStrategy(
function(username, password, done) {
User.findOne({ username: username }, function (err, user) {
if (err) { return done(err); }
if (!user) { return done(null, false); }
if (!user.validPassword(password)) { return done(null, false); }
return done(null, user);
});
}
));
This code is executed on every single request which means that on every request to the server your user is loaded from your database.
Even if you're working with multiple sessions in multiple browsers the result is the same. So it is up to you to handle when and how you want to update your user in your database.
Otherwise if you don't load your user from an external datasource but e.g. deserialize the whole user object from jwt ( which is not recommended unless you really understand what you're doing ) then you need to think of a synchronisation strategy e.g. check some updated flag in db or some cache on deserialization

admin.auth().currentUser; returning undefined in Cloud Function

I am trying to create a function that, when a device is registered in the app, will attach this device uid to the uid of the signed-in user who registered the device (this is in another firestore collection that is automatically created when a user registers).
Here is my code:
exports.addDeviceToUser = functions.firestore.document('device-names/{device}').onUpdate((change, context) => {
const currentUser = admin.auth().currentUser;
const deviceName = context.params.device;
var usersRef = db.collection('users');
var queryRef = usersRef.where('uid', '==', currentUser.uid);
if (authVar.exists) {
return queryRef.update({sensors: deviceName}).then((writeResult => {
return console.log('Device attached');
}));
} else {return console.log('Device attachment failed, user not signed in');}
});
I am consistently getting this error: "TypeError: Cannot read property 'uid' of undefined." Obviously I am not able to access the auth information of the current user. Why?
The Admin SDK doesn't have a sense of current user. When you say admin.auth(), you're getting back an Auth object. As you can see from the API docs, there is no currentUser property on it. Only the Firebase client SDK has a sense of current user, because you use that to get the user logged in.
If you need the client app to tell Cloud Functions code work with the user's identity, you have to send it an ID token from the client, and verify it on the server. Then the server can know who the end user is, and perform actions on their behalf. Typically you do this with an HTTP type trigger. Callable functions transmit this data automatically between the client and server, but you can do it manually yourself using code that works like this sample.
Right now, Firestore triggers don't have immediate access to the end user that made a change in the database. However, if you use the Auth UID of the user as the key of the document, and protect that document with security rules, you can at least infer the UID of the user based on the changes they make to the document by pulling it out of the id of the document that changed.
Because, by design, Cloud Functions executes on the back end and do not hold any information on which user was authenticated when adding/modifying the data in the database.
When writing the data in the 'device-names/{device}' document (from your app), you could include an extra piece of data which is the uid of the current user.

Questions about how passport.js works. Specifically about user.id

I have no id field in my model ,doc, or record or whatever you want to call it. So how come done(null, user.id) works. I have an _id but no id. It looks like a passport object is being added to my session with the _id of the user in the DB, but how did it get the _id is it done automatically? in the docs it says
In this example, only the user ID is serialized to the session
how did it get the id and how did it get the user?
similar example in my code:
passport.serializeUser(function(user, done){
done(null, user.id)
});
passport.deserializeUser(function(id, done){
User.findById(id, function(err, user){
done(err, user);
})
});
What are the steps that it takes to get the user id?
I also have
passport.use("login", new LocalStrategy(function(username, password, done){
User.findOne({username : username}, function(err, user){
if(err){return done(err)}
if(!user){
return done(null, false, {message : "no User has that name"})
}
.......
Does the fact that I use passport.use() somehow connect the user in the DB to the passport methods.
Edit lets say I want to transfer the doc (user) via passports on the name field should I use user.name?
Also I'm not really sure about how serializing works
So how come done(null, user.id) works. I have an _id but no id.
You're using Mongoose, which adds a so-called virtual getter called id to documents, that returns the _id property. So in your case, both user.id and user._id will work (and will return the same).
Does the fact that I use passport.use() somehow connect the user in the DB to the passport methods.
Yes and no. The strategy that you pass to passport.use() implements the authentication process. You have to implement how the entered user information is validated against your database. In the example code, a call to User.findOne() is made, and the result of that call is checked against the supplied information ("Is username a valid username? If so, is password the password that belongs to this user?").
If the username and password match, the done callback is called with the user document as an argument. This document is what Passport will pass around to various other parts, for instance, to passport.serializeUser() (see below).
Also I'm not really sure about how serializing works.
Serializing is used to store information about the user in a "session object". This object should be able to uniquely identify the user. And since user.id (or user._id) is unique to a user, it's a good property to use.
That's where passport.serializeUser() comes in: it gets passed the user document, and it should provide Passport (by calling the callback function) a uniquely identifying piece of information about that user. Hence done(null, user.id).
The session object itself is also uniquely identified by a "session key". This key is stored in a HTTP cookie and sent to the browser when a user logged in successfully. When the browser opens another page on your website, it sends along that cookie, and using the session key in the cookie, the session object is retrieved from the "session store".
The session object contains the unique user id, but not the rest of the user information. So that's where passport.deserializeUser() comes in: it gets passed the id, and performs a database lookup to retrieve the full user document belonging to that id. This is what Passport will make available as req.user in your route handlers.
If all these steps are executed successfully (which isn't always the case, because cookies can expire, users can get deleted, etc), it will mean that Passport was able to positively identify the user, and they don't have to log in again. At least not until the session expires.

Categories

Resources