Always Guest User with XHR

Technical Support
  • I'm working on getting commenting set up on a Ghost blog using Nodebb (making use of the nodebb-plugin-blog-comments plugin).

    Ghost blog:
    NodeBB site:

    The plugin calls a request via javascript on the Ghost page. Looking at the Chrome Developer Options, I get a different response from the api via Javascript than I do just opening the page in my browser.

    Sample request:

    Developer Options (just a relevant chunk):
    user: {uid: 0, username: "[[global:guest]]", userslug: "", fullname: "[[global:guest]]", email: "",…}

    In Browser Tab:

    Because of this issue, the commenting system won't allow me to publish the ghost blog to nodebb for commenting. Instead I see "Comments are disabled."

  • I am continuing to read documentation and guessing that it has something to do with authentication for the API. Does anyone have an example of authenticating via javascript with cookies?

  • @nick-allain You're sort of on the right track... I'll ping @psychobunny for his thoughts, but in the meantime, it sounds like your request to ghost isn't authenticated, possibly because it is not sending the appropriate cookie through the request.

    As that page you link to suggests, the API uses cookie authentication first and foremost, which is why when you access the comments/get link from your browser, you are logged in.

    The plugin code looks ok, in that it executes the XHR withCredentials, but can you confirm that that is the case in the dev tools?

  • Thanks @julian - your message prompted me to look at the cookie itself. Chrome DevTools is flagging an issue that I didn't previously see.

    This Set-Cookie was blocked because it had the "SameSite=strict" attribute but came form a cross-site response which was not the response to a top-level navigation.

    To try to answer you're question, here's what my headers look like. I will freely admit, I'm a little over my head on this! I'm a marketing guy trying to help out his car community 😉

    GET /comments/get/5fe3b20991b86c0039a9800e/0 HTTP/1.1
    Connection: keep-alive
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
    Accept: /
    Sec-Fetch-Site: cross-site
    Sec-Fetch-Mode: cors
    Sec-Fetch-Dest: empty
    Accept-Encoding: gzip, deflate, br
    Accept-Language: en-US,en;q=0.9

    HTTP/1.1 200 OK
    Server: nginx/1.18.0 (Ubuntu)
    Date: Tue, 29 Dec 2020 00:57:44 GMT
    Content-Type: application/json; charset=utf-8
    Content-Length: 5641
    Connection: keep-alive
    X-DNS-Prefetch-Control: off
    Expect-CT: max-age=0
    X-Frame-Options: SAMEORIGIN
    X-Download-Options: noopen
    X-Content-Type-Options: nosniff
    X-Permitted-Cross-Domain-Policies: none
    X-XSS-Protection: 0
    Referrer-Policy: strict-origin-when-cross-origin
    X-Powered-By: Oppositelock
    Content-Security-Policy: frame-ancestors 'self'
    set-cookie: _csrf=qVrBDseAYi8zRdAqIhsffeBz; Path=/; HttpOnly; Secure; SameSite=Strict
    Access-Control-Allow-Headers: X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept
    Access-Control-Allow-Credentials: true
    ETag: W/"1609-C37JNRX5kkSgV4I14TWs+cPivkE"

  • @nick-allain ah, you'll have to set the cookie domain in the ACP to contain both domains.

    Careful what value you set, if you set the wrong one, you might lock yourself out of the ACP!

  • @julian Thanks! I managed to get it almost working. Now I get a wonderfully generic {"error":"Unable to post topic"}

  • @nick-allain Are you able to make changes to the plugin files? It looks like the error is coming from the blog-comments plugin itself.

    If you can, can you add console.log(err, result); after line 185?

  • @julian It took a few days to have the admin add it, but here's the robust error:

    Error: Please enter a longer title. Titles should contain at least 3 character(s).
    at check (/home/ubuntu/nodebb/src/topics/create.js:253:10)
    at Object.Topics.checkTitle (/home/ubuntu/nodebb/src/topics/create.js:239:3)
    at (/home/ubuntu/nodebb/src/topics/create.js:71:10)
    at Callbackified (util.js:210:5)
    at Object.wrapperCallback [as post] (/home/ubuntu/nodebb/src/promisify.js:46:23)
    at /home/ubuntu/nodebb/node_modules/nodebb-plugin-blog-comments/library.js:178:11
    at /home/ubuntu/nodebb/node_modules/async/dist/async.js:2955:19
    at wrapper (/home/ubuntu/nodebb/node_modules/async/dist/async.js:268:20)
    at iterateeCallback (/home/ubuntu/nodebb/node_modules/async/dist/async.js:421:28)
    at /home/ubuntu/nodebb/node_modules/async/dist/async.js:321:20 undefined

  • So I was able to solve the previously mentioned issue. Ghost.js looks for the title of a post in a SPAN with the id of "nbb-title". For some reason, that span was empty. I used handlebars and .innerHTML to write the title to that span.

    However, I'm now back to what appears to be a header issue - but this time it might on the NodeBB side:

    2021-01-24T18:44:04.051Z [4567/62671] - warn: [nodebb-plugin-blog-comments] Origin ( does not match hostUrls: *
    2021-01-24T18:44:10.221Z [4567/62671] - warn: [nodebb-plugin-blog-comments] Origin ( does not match hostUrls: *
    Error: You do not have enough privileges for this action.
        at (/home/ubuntu/nodebb/src/topics/create.js:86:10)
        at processTicksAndRejections (internal/process/task_queues.js:97:5) undefined

    Our nodeBB is hosted at:
    The blog is hosted at: (this is exactly what is specified in the plugin.


  • @nick-allain Hm... from the sounds of it, Ghost may be trying to publish the article as a guest user, which isn't right.

    What version of Ghost are you running? It might be time for @psychobunny to step in...

  • @julian I agree with your analysis. I'm on Ghost 3.41.2

    @psychobunny - any ideas on things I could try?

  • hi @Nick-Allain this error message:
    [nodebb-plugin-blog-comments] Origin ( does not match hostUrls: *

    suggests that in the ACP the link to your blog is actually set as *.

    I know you attached a screenshot showing otherwise, but could you double check and refresh the page (in case for ex., there was an error saving?) to see? If it's still an issue, I wouldn't mind temporary admin access to have a look, feel free to DM me for that

Suggested Topics

  • 0 Votes
    18 Posts

    @julian said in Re-link deleted user's content when they re-join?:

    Right now we just save the @mention text, not the actual user association.

    And provided this does not provide direct attribution, then this is in fact acceptable and within GDPR. For example, having John Smith as the @ name is obviously providing attribution (but you could argue that the name means nothing given it's popularity and it would be a valid point), but a handle like "theWasp" doesn't - unless there is a post that directly correlates that handle to a physical person.

    For example, if someone posted "@thewasp is John Smith who lives at ....." (you get the picture), then this clearly provides direct attribution, and you'd have no foundation to keep data in this manner. Unfortunately, the only way around something like this is to develop a plugin that performs regex matches and purposely looks for data to redact or expunge.

    This specific method can be expensive (in the performance sense) on large forums and associated databases, and complex in nature owing to the type of regex you'd need to build. Even then, you cannot possibly catch everything because you'd run into issues such as the regex being too "greedy" (affecting large portions of text in a gratuitous nature) or too lenient (not going far enough). There is seldom any sensible balance - it's either too much, or not enough.

    You'd need to search the entire database looking for possible matches, and that would take significant effort to ensure you removed or redacted information that could provide attribution.

    This is where the waters of GDPR and privacy become muddied in the sense that you need to impose sane limits on what is necessary to either remove or redact. For example, if a user claimed that "the" personally identified them, you couldn't remove it for obvious reasons otherwise literally everything your other users have posted would need redaction, and that makes zero sense.

    This is why "legitimate interest" exists in the first place. You are entitled to keep data intact if it is considered impactful to the consistency if you were to remove it, but you cannot claim implied consent (assuming it's ok to keep without foundation).

    GDPR is a complex animal and most people either go way overboard, or do nothing at all, which is arguably worse. NodeBB has this balance just right.

  • 0 Votes
    11 Posts

    You have to remove our comment out the assets location block. It may be possible to just exclude uploads, but you'll need to research the nginx syntax for that yourself.

  • 1 Votes
    10 Posts

    @dunlix Thank you

  • 0 Votes
    3 Posts

    @PitaJ said in Use SQL database for NodeBB user accounts:

    @Jarko we suggest using oauth or session sharing to accomplish this.

    Session sharing looks promising, thank you for your input. I'll give it a try!

  • 0 Votes
    2 Posts

    Hmm, that sounds like a bug, you shouldn't be able to create two users with the same name.

    When you delete the account, it removes it's entry in the 'userslug:uid' set which that route uses to lookup your profile info, as well as a bunch of other sets. But it doesn't delete your user object at 'user:{uid}' (because your other account has a different uid). You would have to re-add your username to the sets it's removed from in user.delete. I'm unfortunately not sure the exact command you would have to use in mongod though. 😞 You should be able to find your original users uid in /api/users though. 🐦 Renaming the account from the acp may also work.