Meteor 3 - "Meteor.userId can only be invoked in method calls or publications."?

I’m working on updating my app to Meteor 3.0rc0.

I’m seeing this a lot, on the client, and also on the server in my GraphQL resolvers:

Meteor.userId can only be invoked in method calls or publications.

For example, in a GraphQL resolver on the server, this line throws:

 const userData = Meteor.user();

What’s a good way to handle this?

I’m getting the impression that I need to set up a couple of Meteor methods and then call them from an async context with await:

Meteor.methods({
    'getUserId': function() {
        return this.userId;
    }
});

Meteor.methods({
    'getUser': function() {
        return this.user;
    }
});

Does that sound right, or am I on the wrong track?

I’m trying this:

Meteor.call('getUser', (error, user) => {
    if (error) {
        // Handle the error
    } else {
        console.log(user)
    }

…but I’m getting undefined back in the user object. I’ve never created Meteor functions. Am I missing something?

You can just use Meteor.user() in client too to get user. Meteor.user() in server too instead of this.user.

With meteor 2, I could always use meteor.userId() in my resolvers. With meteor 3, I get a message saying it can only be used in a method or a publication.

Ok maybe it’s something 3.0 related then I haven’t migrated yet :slight_smile:

Thanks for reporting this. I’ll try to simulate it and see what’s happening.

1 Like

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.

  1. When are you using these values

  2. Are you certain that the user has already logged in by the moment you are using them?

  3. Open the console of your browser and execute Meteor.user() while running the app. What did you get?

1 Like
  1. I’m trying to add the newly registered user to a role, and thus the user Id is useful for that.

  2. 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.

  3. 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.