Unable to generate new token using write API
-
curl --request POST
--url http://localhost:4567/api/v3/utilities/login
--header 'Content-Type: application/json'
--cookie express.sid=s%253A0CeC6fT33naRGdLKqGWJfiRgeMSF0RNf.fRo8vw8Na0coWmVsqoLHJVpNoN%252FMRsh%252FGB%252F7eTYIEdE
--data '{
"username": "Soldatino",
"password": "s3cre7password"
}'curl --request GET
--url http://localhost:4567/api/config
--cookie express.sid=s%253A0CeC6fT33naRGdLKqGWJfiRgeMSF0RNf.fRo8vw8Na0coWmVsqoLHJVpNoN%252FMRsh%252FGB%252F7eTYIEdEcurl --request POST
--url http://localhost:4567/api/v3/users/65/tokens
--header 'Content-Type: application/json'
--header 'X-Csrf-Token: 6shtSbjj-tgQ9z509Qd6vhVuzS7nd9GwMVbE'
--cookie express.sid=s%253A0CeC6fT33naRGdLKqGWJfiRgeMSF0RNf.fRo8vw8Na0coWmVsqoLHJVpNoN%252FMRsh%252FGB%252F7eTYIEdEWhen I pass the x-csrf-token obtained with GET /config the result is always the same.
"Forbidden"
-
-
@Carlo-Lancia I was able to generate the token using the following cURL commands.
Note that these commands were run against my local dev instance, so the express sid and csrf token are not of consequence
curl localhost:4567/api/config --cookie express.sid=s%3A89Lr9fB_95aGYpvh8fnW1HFwvI6i7vWu.jQS5qdiLh1yCVLfhdUChIufHSIysIKGNaIXgzfQ%2Bxns
Which responded with the expected config json.
curl -X POST --data "csrf_token=ab57cdb4f7134f3ea54ba1d8601458d3695d6bc856fc26a377503f44f83ce6591d83ddff1a029faa5f7df869e9495e125b90c60fa67cdd6a8c0968a3447eda9c" localhost:4567/api/v3/users/1/tokens --cookie express.sid=s%3A89Lr9fB_95aGYpvh8fnW1HFwvI6i7vWu.jQS5qdiLh1yCVLfhdUChIufHSIysIKGNaIXgzfQ%2Bxns
which responded with the new token:
{ "status": { "code": "ok", "message": "OK" }, "response": { "token": "b4ea969b-276f-415f-b16f-830674d3a2ab", "uid": 1, "description": "", "timestamp": 1680703250905 } }
-
How do you make the csrf_token?
"csrf_token=ab57cdb4f7134f3ea54ba1d8601458d3695d6bc856fc26a377503f44f83ce6591d83ddff1a029faa5f7df869e9495e125b90c60fa67cdd6a8c0968a3447eda9c"
-
When I call /api/config, I just get this below:
"csrf_token": "5QqLa7mm-JTOaABefScoyGw6n3jrmsYSrHno",
Do you need to convert it to hexadecimal?
-
I do not know what you mean.
I call only /api/v3 -
NodeBB version 3. Not the v3 API, they are different things (although I can see how you could be confused).
You're currently on version 2, version 3 is still unreleased.
Both versions have /api/v3, but the csrf generation library is different in NodeBB v2. That's all.
-
sorry for my confusion.
-
@Carlo-Lancia Yes, still works fine:
curl -X POST -H "x-csrf-token: qbdvOXla-rBob0mHA5NBXlFLIbTZJd7z6do0" localhost:4567/api/v3/users/1/tokens --cookie express.sid=s%3A89Lr9fB_95aGYpvh8fnW1HFwvI6i7vWu.jQS5qdiLh1yCVLfhdUChIufHSIysIKGNaIXgzfQ%2Bxns
{ "status": { "code": "ok", "message": "OK" }, "response": { "token": "aa8b3e37-9d75-4f2b-86ab-d90be15b47f7", "uid": 1, "description": "", "timestamp": 1680705230030 } }
-
Thank you for the time you have dedicated to me.
Now I do some tests,
I try to do it. -
@julian
Hi Julian, How are you?
I was able to test your indications, the results are different from what I expected.
The administrative user actually generates the token successfully.While for a new user the indicated sequence does not have the same effect.
Where am I doing wrong?
I add the API calls to the nodeBB system below.
ADMINISTRATIVE USER "Carlo.Merola"
REQUEST LOGIN
curl --request POST \ --url http://localhost:4567/api/v3/utilities/login \ --header 'Content-Type: application/json' \ --cookie express.sid=s%253AkHYV_owxQoxuaVwGKAA5DE0FpgOuW83p.lbtUZdJHW8LEgPy3GLYncwdLXuQTzsfi4ubk%252BZ5IFJo \ --data '{ "username": "Carlo.Merola", "password": "omissis" }'
RESPONSE OK
{ "status": { "code": "ok", "message": "OK" }, "response": { "uid": 3, "username": "Carlo.Merola", "userslug": "carlo-merola", "picture": "/assets/uploads/profile/3-profileavatar-1676988051741.png", "status": "offline", "postcount": 0, "reputation": 0, "email:confirmed": 1, "lastonline": 1681297625750, "flags": null, "banned": false, "banned:expire": 0, "joindate": 1674838394707, "fullname": null, "displayname": "Carlo.Merola", "icon:text": "C", "icon:bgColor": "#673ab7", "joindateISO": "2023-01-27T16:53:14.707Z", "lastonlineISO": "2023-04-12T11:07:05.750Z", "banned_until": 0, "banned_until_readable": "Not Banned" } }
REQUEST CONFIG
curl --request GET \ --url http://localhost:4567/api/config \ --cookie express.sid=s%253AdWjgq6Xe5i388H4VEXhIzyr4um9uVeZB.bvy78e9PYmjNx%252FEmvR07DdjPD8UWvCDC7CyRiNSvI%252FQ
RESPONSE OK
{ "relative_path": "", "upload_url": "/assets/uploads", "asset_base_url": "/assets", "assetBaseUrl": "/assets", "siteTitle": "HyperCuTe", "browserTitle": "HyperCuTe", "titleLayout": "{pageTitle} | {browserTitle}", "showSiteTitle": true, "maintenanceMode": false, "minimumTitleLength": 3, "maximumTitleLength": 255, "minimumPostLength": 8, "maximumPostLength": 32767, "minimumTagsPerTopic": 0, "maximumTagsPerTopic": 5, "minimumTagLength": 3, "maximumTagLength": 15, "undoTimeout": 10000, "useOutgoingLinksPage": false, "allowGuestHandles": false, "allowTopicsThumbnail": true, "usePagination": true, "disableChat": false, "disableChatMessageEditing": false, "maximumChatMessageLength": 3000, "socketioTransports": [ "polling", "websocket" ], "socketioOrigins": "http://localhost:4567:*", "websocketAddress": "", "maxReconnectionAttempts": 5, "reconnectionDelay": 1500, "topicsPerPage": 20, "postsPerPage": 20, "maximumFileSize": 20480, "theme:id": "nodebb-theme-vanilla", "theme:src": "https://cdn.jsdelivr.net/npm/[email protected]/spacelab/bootstrap.min.css", "defaultLang": "it", "userLang": "it", "loggedIn": true, "uid": 3, "cache-buster": "v=88rphh6u1aq", "topicPostSort": "oldest_to_newest", "categoryTopicSort": "newest_to_oldest", "csrf_token": "vtVKfNxM-MmApXIW16ROi22mizlKf6QNyL-4", "searchEnabled": true, "searchDefaultInQuick": "titles", "bootswatchSkin": "", "enablePostHistory": true, "timeagoCutoff": 30, "timeagoCodes": [ "af", "am", "ar", "az-short", "az", "be", "bg", "bs", "ca", "cs", "cy", "da", "de-short", "de", "dv", "el", "en-short", "en", "es-short", "es", "et", "eu", "fa-short", "fa", "fi", "fr-short", "fr", "gl", "he", "hr", "hu", "hy", "id", "is", "it-short", "it", "ja", "jv", "ko", "ky", "lt", "lv", "mk", "nl", "no", "pl", "pt-br-short", "pt-br", "pt-short", "pt", "ro", "rs", "ru", "rw", "si", "sk", "sl", "sq", "sr", "sv", "th", "tr-short", "tr", "uk", "ur", "uz", "vi", "zh-CN", "zh-TW" ], "cookies": { "enabled": false, "message": "This website uses cookies to ensure you get the best experience on our website.", "dismiss": "Got it!", "link": "Learn More", "link_url": "https://www.cookiesandyou.com" }, "thumbs": { "size": 512 }, "iconBackgrounds": [ "#f44336", "#e91e63", "#9c27b0", "#673ab7", "#3f51b5", "#2196f3", "#009688", "#1b5e20", "#33691e", "#827717", "#e65100", "#ff5722", "#795548", "#607d8b" ], "emailPrompt": 1, "useragent": { "isYaBrowser": false, "isAuthoritative": false, "isMobile": false, "isMobileNative": false, "isTablet": false, "isiPad": false, "isiPod": false, "isiPhone": false, "isiPhoneNative": false, "isAndroid": false, "isAndroidNative": false, "isBlackberry": false, "isOpera": false, "isIE": false, "isEdge": false, "isIECompatibilityMode": false, "isSafari": false, "isFirefox": false, "isWebkit": false, "isChrome": false, "isKonqueror": false, "isOmniWeb": false, "isSeaMonkey": false, "isFlock": false, "isAmaya": false, "isPhantomJS": false, "isEpiphany": false, "isDesktop": false, "isWindows": false, "isLinux": false, "isLinux64": false, "isMac": false, "isChromeOS": false, "isBada": false, "isSamsung": false, "isRaspberry": false, "isBot": false, "isCurl": false, "isAndroidTablet": false, "isWinJs": false, "isKindleFire": false, "isSilk": false, "isCaptive": false, "isSmartTV": false, "isUC": false, "isFacebook": false, "isAlamoFire": false, "isElectron": false, "silkAccelerated": false, "browser": "insomnia", "version": "2022.7.5", "os": "unknown", "platform": "unknown", "geoIp": {}, "source": "insomnia/2022.7.5", "isWechat": false }, "acpLang": "it", "openOutgoingLinksInNewTab": false, "topicSearchEnabled": false, "composer-default": {}, "markdown": { "highlight": 1, "highlightLinesLanguageList": [], "theme": "default.css", "defaultHighlightLanguage": "" }, "emojiCustomFirst": false }
REQUEST TOKEN
curl --request POST \ --url http://localhost:4567/api/v3/users/3/tokens \ --header 'x-csrf-token: vtVKfNxM-MmApXIW16ROi22mizlKf6QNyL-4' \ --cookie express.sid=s%253AdWjgq6Xe5i388H4VEXhIzyr4um9uVeZB.bvy78e9PYmjNx%252FEmvR07DdjPD8UWvCDC7CyRiNSvI%252FQ
RESPONSE OK
{ "status": { "code": "ok", "message": "OK" }, "response": { "token": "ac9bfc1e-e31d-4779-b900-71e3c15f5fac", "uid": 3, "description": "", "timestamp": 1681300461177 } }
NEW REGISTERED USER "Soldatino"
REQUEST LOGIN
curl --request POST \ --url http://localhost:4567/api/v3/utilities/login \ --header 'Content-Type: application/json' \ --cookie express.sid=s%253ATiY7RPVN5jBsBLpjCcf28kW_jh4-3R6P.eOp1l18tfazAfL2QvgpD%252BU9zoDv08X9KfJo4rE88O38 \ --data '{ "username": "Soldatino", "password": "omissis" }'
RESPONSE OK
{ "status": { "code": "ok", "message": "OK" }, "response": { "uid": 65, "username": "Soldatino", "userslug": "soldatino", "picture": null, "status": "offline", "postcount": 0, "reputation": 0, "email:confirmed": 1, "lastonline": 1681298877112, "flags": null, "banned": false, "banned:expire": 0, "joindate": 1679315311139, "fullname": null, "displayname": "Soldatino", "icon:text": "S", "icon:bgColor": "#673ab7", "joindateISO": "2023-03-20T12:28:31.139Z", "lastonlineISO": "2023-04-12T11:27:57.112Z", "banned_until": 0, "banned_until_readable": "Not Banned" } }
REQUEST CONFIG
curl --request GET \ --url http://localhost:4567/api/config \ --cookie express.sid=s%253ATiY7RPVN5jBsBLpjCcf28kW_jh4-3R6P.eOp1l18tfazAfL2QvgpD%252BU9zoDv08X9KfJo4rE88O38
RESPONSE OK
{ "relative_path": "", "upload_url": "/assets/uploads", "asset_base_url": "/assets", "assetBaseUrl": "/assets", "siteTitle": "HyperCuTe", "browserTitle": "HyperCuTe", "titleLayout": "{pageTitle} | {browserTitle}", "showSiteTitle": true, "maintenanceMode": false, "minimumTitleLength": 3, "maximumTitleLength": 255, "minimumPostLength": 8, "maximumPostLength": 32767, "minimumTagsPerTopic": 0, "maximumTagsPerTopic": 5, "minimumTagLength": 3, "maximumTagLength": 15, "undoTimeout": 10000, "useOutgoingLinksPage": false, "allowGuestHandles": false, "allowTopicsThumbnail": true, "usePagination": true, "disableChat": false, "disableChatMessageEditing": false, "maximumChatMessageLength": 3000, "socketioTransports": [ "polling", "websocket" ], "socketioOrigins": "http://localhost:4567:*", "websocketAddress": "", "maxReconnectionAttempts": 5, "reconnectionDelay": 1500, "topicsPerPage": 20, "postsPerPage": 20, "maximumFileSize": 20480, "theme:id": "nodebb-theme-vanilla", "theme:src": "https://cdn.jsdelivr.net/npm/[email protected]/spacelab/bootstrap.min.css", "defaultLang": "it", "userLang": "it", "loggedIn": true, "uid": 65, "cache-buster": "v=88rphh6u1aq", "topicPostSort": "oldest_to_newest", "categoryTopicSort": "newest_to_oldest", "csrf_token": "p3Yq9OQ7-O1EpqDzJkX1TvWuJ1JzBvuAydpU", "searchEnabled": true, "searchDefaultInQuick": "titles", "bootswatchSkin": "", "enablePostHistory": true, "timeagoCutoff": 30, "timeagoCodes": [ "af", "am", "ar", "az-short", "az", "be", "bg", "bs", "ca", "cs", "cy", "da", "de-short", "de", "dv", "el", "en-short", "en", "es-short", "es", "et", "eu", "fa-short", "fa", "fi", "fr-short", "fr", "gl", "he", "hr", "hu", "hy", "id", "is", "it-short", "it", "ja", "jv", "ko", "ky", "lt", "lv", "mk", "nl", "no", "pl", "pt-br-short", "pt-br", "pt-short", "pt", "ro", "rs", "ru", "rw", "si", "sk", "sl", "sq", "sr", "sv", "th", "tr-short", "tr", "uk", "ur", "uz", "vi", "zh-CN", "zh-TW" ], "cookies": { "enabled": false, "message": "This website uses cookies to ensure you get the best experience on our website.", "dismiss": "Got it!", "link": "Learn More", "link_url": "https://www.cookiesandyou.com" }, "thumbs": { "size": 512 }, "iconBackgrounds": [ "#f44336", "#e91e63", "#9c27b0", "#673ab7", "#3f51b5", "#2196f3", "#009688", "#1b5e20", "#33691e", "#827717", "#e65100", "#ff5722", "#795548", "#607d8b" ], "emailPrompt": 1, "useragent": { "isYaBrowser": false, "isAuthoritative": false, "isMobile": false, "isMobileNative": false, "isTablet": false, "isiPad": false, "isiPod": false, "isiPhone": false, "isiPhoneNative": false, "isAndroid": false, "isAndroidNative": false, "isBlackberry": false, "isOpera": false, "isIE": false, "isEdge": false, "isIECompatibilityMode": false, "isSafari": false, "isFirefox": false, "isWebkit": false, "isChrome": false, "isKonqueror": false, "isOmniWeb": false, "isSeaMonkey": false, "isFlock": false, "isAmaya": false, "isPhantomJS": false, "isEpiphany": false, "isDesktop": false, "isWindows": false, "isLinux": false, "isLinux64": false, "isMac": false, "isChromeOS": false, "isBada": false, "isSamsung": false, "isRaspberry": false, "isBot": false, "isCurl": false, "isAndroidTablet": false, "isWinJs": false, "isKindleFire": false, "isSilk": false, "isCaptive": false, "isSmartTV": false, "isUC": false, "isFacebook": false, "isAlamoFire": false, "isElectron": false, "silkAccelerated": false, "browser": "insomnia", "version": "2022.7.5", "os": "unknown", "platform": "unknown", "geoIp": {}, "source": "insomnia/2022.7.5", "isWechat": false }, "acpLang": "it", "openOutgoingLinksInNewTab": false, "topicSearchEnabled": false, "composer-default": {}, "markdown": { "highlight": 1, "highlightLinesLanguageList": [], "theme": "default.css", "defaultHighlightLanguage": "" }, "emojiCustomFirst": false }
REQUEST TOKEN
curl --request POST \ --url http://localhost:4567/api/v3/users/65/tokens \ --header 'x-csrf-token: p3Yq9OQ7-O1EpqDzJkX1TvWuJ1JzBvuAydpU' \ --cookie express.sid=s%253ATiY7RPVN5jBsBLpjCcf28kW_jh4-3R6P.eOp1l18tfazAfL2QvgpD%252BU9zoDv08X9KfJo4rE88O38
RESPONSE NOK
{ "status": { "code": "forbidden", "message": "You do not have enough privileges for this action." }, "response": {} }
-
Hi @Carlo-Lancia, I did some digging into the history of the implementation and it seems to be that this route was not intended to be called by regular users. The logic restricting access to administrators has been there since the beginning.
This is not to say that it will always be this way. If I had to guess my thought process (again, this was nearly three years ago), I would fathom that I restricted access because allowing regular users to create their own tokens necessitates building out a custom UI for users to manage their tokens, as well as a corresponding GET route to retrieve tokens, and a backend for toggling the feature on and off, etc. My focus at that time was to port the logic from the Write API plugin as quickly as possible.
-
In the meantime, if you wish to allow users to create their own tokens (either by using another token or by using a cookie sesson), go to the
usersAPI.generateToken
method insrc/api/users.js
, and remove the following line:await hasAdminPrivilege(caller.uid, 'settings');
That is the simplest way to bypass the security of the controller so that anyone can create a token for themselves.
-
Hi Julian,
I just modified the file "src/controllers/write/users.js", as you indicated. Now I can generate the token.
Ok!
Grazie -