Ok maybe it’s something 3.0 related then I haven’t migrated yet
Thanks for reporting this. I’ll try to simulate it and see what’s happening.
Here’s a small demo app.
- Incorporates minor updates to Meteor Apollo Skeleton for Meteor 3
- Does not require Meteor package swydo:apollo
- Demonstrates that Meteor.user() cannot yet be accessed in resolvers
I’m actually running into this right now. Did a proper fix ever get posted?
I get null
for both
Meteor.userId()
and
Meteor.user()
on the client side.
-
When are you using these values
-
Are you certain that the user has already logged in by the moment you are using them?
-
Open the console of your browser and execute
Meteor.user()
while running the app. What did you get?
-
I’m trying to add the newly registered user to a role, and thus the user Id is useful for that.
-
I believe they are logged in after the initial creation, but may need to put some logic to make sure they are logged in already.
-
When I am logged in and have the app running, I can see the
Meteor.user()
object data returned in the web console.
It was #2 for sure. I was calling the Meteor.user()
too soon, and the user wasn’t fully logged in yet. Still getting used to this whoel async / await
stuff. Now I await
the account creation, then it gives me the user object. Thank you.
Also potentially helpful:
const isLoggingIn = Meteor.loggingIn();
Check the documentation about Accounts.onCreateUser()
, which should be the ideal place to add default roles to a new account.
Erratum:
I only realized now that I was talking about a different function: Accounts.updateOrCreateUserFromExternalService()
which returns the created user.
@vikr00001 yes, you can use userId and user only in methods and publications. If you want to use it in your Appollo or somewhere else, for example Meteor Cron, you cannot use Meteor.userAsync() or Meteor.userId();
In this case, you need to get user “manually”. This is the most simple way:
Get userId on client side: Meteor.userId();
Get loginToken on clientSide: Meteor: Meteor._localStorage.getItem("Meteor.loginToken")
(now put in into header or body of the request)
On the server, create and use your own method getUserAsync(userId: string, token: string) which will return user’s object; When you will be in this point, If you will need, you can modify it to make it more secure, use your own token, …whatever you want.
It may not be secure to get Meteor.userId()
on the client and send it to the server. Here is server-side code to get Meteor.userId()
:
Note the post right after that one as well.
Is it problem, if you validate userId and token on server side?
It seems to work fine. The security risk of sending Meteor.userId() from client to server, is that someone may be able to send a different Meteor.userId() from the client to your server, and so your server would update the wrong user.
But if you send userId and also user token, on server you need to validate before you start to do anything.
Interesting. Please describe how you validate the userId on the server.
You don’t use the internal meteor method, but you will create your own, for example async
getLoggedUserAsync(userId, token) {
// you can also modify, if your user is active, or whatever you want
return (await Meteor.users.findOneAsync({
_id: userId,
"services.resume.loginTokens.hashedToken": Accounts._hashLoginToken(loginToken),
}, {fields: {private: 0, ....another fields}})) as IUser;
}
check(userId, String);
check(token, String);
const currentUser = getLoggedUserAsync(userId, token);
Later you can somehow modify your method to prevent bruteforce.
Hmmm… it looks like you’re relying on the userId provided by the client. A hacker might be able to find the userId of another user of your app. If someone uses your app and leaves their computer unattended, someone could type Meteor.userId()
into the console and get it.
However, maybe the approach you describe is correct for your use case.
Can you explain it more deeper? Because to found another userId he must know also his token. Or I’m thinking wrong?
Hmmm… that might work. I’ve taken the view that, since I can look up the userId via the loginToken, I won’t send the userId from the client to the server. But your approach may be perfectly correct. I’ll leave it for others here to comment.
I think, userId with token is more secure, but you are boss of your project