Talk: Getting error: " Cannot return null for non-nullable field User.id" when trying to use tokenUserNotFound plugin

Created on 5 Sep 2018  路  3Comments  路  Source: coralproject/talk

I am trying to authenticate user using tokenUserNotFound

Here is my code which I got it after going through this thread : https://github.com/coralproject/talk/issues/1820

const UserModel = require('../../../models/user');
module.exports = {
    tokenUserNotFound: async ({jwt, token}) => {
          console.log("222222222222222222222222222222222222222222222222222222222222222222222222222222222");
      console.log(jwt);
        console.log(jwt.ssoCode);
      console.log("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"); 
      let data={"displayName":"hmmminaee","email":"[email protected]"};
      console.log(profile);

      const user = await UserModel.findOneAndUpdate(
        {
          id: jwt.ssoCode,
        },
        {
          id: jwt.ssoCode,
          username: data.email,
          lowercaseUsername: data.email.toLowerCase(),
          profiles: [
            {
              provider: 'local',
              id: jwt.ssoCode,
            },
          ],
          status: {
            username: {
              status: 'SET',
              history: [
                {
                  status: 'SET',
                },
              ],
            },
          },
          metadata: {
            displayName: data.displayName,
          },
        },
        {
          setDefaultsOnInsert: true,
          new: true,
          upsert: true,
        }
      );
      console.log(user);


      return user;
    }
};

and I get the following error:

Error: Cannot return null for non-nullable field User.id.
    at completeValue (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:599:13)
    at completeValueWithLocatedError (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:546:21)
    at completeValueCatchingError (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:515:12)
    at resolveField (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:467:10)
    at /hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:314:18
    at Array.reduce (<anonymous>)
    at executeFields (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:311:42)
    at collectAndExecuteSubfields (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:749:10)
    at completeObjectValue (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:731:10)
    at completeValue (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:628:12)
    at completeValueWithLocatedError (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:546:21)
    at completeValueCatchingError (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:521:21)
    at resolveField (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:467:10)
    at /hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:314:18
    at Array.reduce (<anonymous>)
    at executeFields (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:311:42)
    at executeOperation (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:239:122)
    at executeImpl (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:136:26)
    at Object.execute (/hamed-test-talk-install-manual/talk/node_modules/graphql/execution/execute.js:113:150)
    at doRunQuery (/hamed-test-talk-install-manual/talk/node_modules/apollo-server-core/dist/runQuery.js:122:42)
    at /hamed-test-talk-install-manual/talk/node_modules/apollo-server-core/dist/runQuery.js:21:56
    at process._tickCallback (internal/process/next_tick.js:68:7)

when I print the user returned I get:

{ status:
   { username: { status: 'SET', history: [Array] },
     banned: { status: false, history: [] },
     suspension: { until: null, history: [] } },
  role: 'COMMENTER',
  ignoresUsers: [],
  _id: 5b868987a394376e0f5748e9,
  id: null,
  __v: 0,
  created_at: 2018-08-29T11:54:47.448Z,
  lowercaseUsername: '[email protected]',
  metadata: { displayName: 'hmmminaee' },
  profiles: [ { provider: 'local' } ],
  tags: [],
  tokens: [],
  updated_at: 2018-08-29T12:23:35.409Z,
  username: '[email protected]' }

and when I print the jwt token this is what I have:

{
  "iat": 1535546389,
  "exp": 1557146389,
  "aud": "talk",
  "iss": "https://comment3.stg2.dev-telegraphjournal.com/",
  "sub": "1",
  "jti": "7a94206d-090b-440e-a72a-900d58ab6a1f"
}

and jwt.ssoCode returns undefined.
I generated the token from the talk token example to isolate the issue. So at this point I get the error saying the Id cannot be null(and _id has a value) and I have no idea what I should provide to avoid it.

Any idea?

troubleshooting help

Most helpful comment

I think that the example that @kgardnr provided was from a different style of authentication.

You should instead use code similar to this:

const UserModel = require("../../../models/user");
module.exports = {
  tokenUserNotFound: async ({ jwt, token }) => {
    // Assuming that the user's ID is located in the "sub" claim of the token.
    const userID = jwt.sub;

    // Retrieve the user profile specified with the given token payload, this
    // example is going to assume that you have a function that will make the
    // correct call to your identity service in order to get the user details
    // with the appropriate credentials.
    const profile = {
      displayName: "hmmminaee",
      email: "[email protected]",
    };

    const user = await UserModel.findOneAndUpdate(
      {
        id: userID,
      },
      {
        id: userID,
        username: profile.email,
        lowercaseUsername: profile.email.toLowerCase(),
        profiles: [
          {
            // Here, we're specifying the custom provider name that is specific
            // to the organization's identity services.
            provider: "brunswicknews",
            id: userID,
          },
        ],
        status: {
          username: {
            // Because we're setting the username now, we set the user's username
            // status to SET.
            status: "SET",
            history: [
              {
                status: "SET",
              },
            ],
          },
        },
        metadata: {
          displayName: profile.displayName,
        },
      },
      {
        setDefaultsOnInsert: true,
        new: true,
        upsert: true,
      }
    );

    return user;
  },
};

That should work for you @hminaeeBrunswicknews!

Note that the code that @kgardnr posted, ssoCode should have been sub, as ssoCode is used in a different implementation.

All 3 comments

I think that the example that @kgardnr provided was from a different style of authentication.

You should instead use code similar to this:

const UserModel = require("../../../models/user");
module.exports = {
  tokenUserNotFound: async ({ jwt, token }) => {
    // Assuming that the user's ID is located in the "sub" claim of the token.
    const userID = jwt.sub;

    // Retrieve the user profile specified with the given token payload, this
    // example is going to assume that you have a function that will make the
    // correct call to your identity service in order to get the user details
    // with the appropriate credentials.
    const profile = {
      displayName: "hmmminaee",
      email: "[email protected]",
    };

    const user = await UserModel.findOneAndUpdate(
      {
        id: userID,
      },
      {
        id: userID,
        username: profile.email,
        lowercaseUsername: profile.email.toLowerCase(),
        profiles: [
          {
            // Here, we're specifying the custom provider name that is specific
            // to the organization's identity services.
            provider: "brunswicknews",
            id: userID,
          },
        ],
        status: {
          username: {
            // Because we're setting the username now, we set the user's username
            // status to SET.
            status: "SET",
            history: [
              {
                status: "SET",
              },
            ],
          },
        },
        metadata: {
          displayName: profile.displayName,
        },
      },
      {
        setDefaultsOnInsert: true,
        new: true,
        upsert: true,
      }
    );

    return user;
  },
};

That should work for you @hminaeeBrunswicknews!

Note that the code that @kgardnr posted, ssoCode should have been sub, as ssoCode is used in a different implementation.

Completely separately from this issue: would your team be interested in a call with us, to talk about your community/comments strategy, and also our multi-tenancy hosting packages? Let me know! I'm [email protected]

Thanks @losowsky please check your email.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

cristiandean picture cristiandean  路  5Comments

allanassis picture allanassis  路  3Comments

tomasdev picture tomasdev  路  4Comments

cristiandean picture cristiandean  路  3Comments

hminaeeBrunswicknews picture hminaeeBrunswicknews  路  4Comments