{"id":15552153,"url":"https://github.com/bahmutov/csrf-login","last_synced_at":"2025-09-28T20:30:52.604Z","repository":{"id":36312070,"uuid":"40616703","full_name":"bahmutov/csrf-login","owner":"bahmutov","description":"Login from command line to the websites that use CSRF protection","archived":false,"fork":false,"pushed_at":"2017-02-15T15:07:17.000Z","size":44,"stargazers_count":20,"open_issues_count":3,"forks_count":6,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-16T21:51:24.137Z","etag":null,"topics":["csrf","csrf-protection","csrf-tokens"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bahmutov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-08-12T18:13:28.000Z","updated_at":"2024-07-17T23:34:48.000Z","dependencies_parsed_at":"2022-09-05T06:51:13.204Z","dependency_job_id":null,"html_url":"https://github.com/bahmutov/csrf-login","commit_stats":null,"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fcsrf-login","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fcsrf-login/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fcsrf-login/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahmutov%2Fcsrf-login/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bahmutov","download_url":"https://codeload.github.com/bahmutov/csrf-login/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234558770,"owners_count":18852281,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csrf","csrf-protection","csrf-tokens"],"created_at":"2024-10-02T14:09:54.176Z","updated_at":"2025-09-28T20:30:52.297Z","avatar_url":"https://github.com/bahmutov.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# csrf-login\n\n\u003e Login from command line to the websites that use CSRF protection\n\n[![NPM][csrf-login-icon] ][csrf-login-url]\n\n[![Build status][csrf-login-ci-image] ][csrf-login-ci-url]\n[![dependencies][csrf-login-dependencies-image] ][csrf-login-dependencies-url]\n[![devdependencies][csrf-login-devdependencies-image] ][csrf-login-devdependencies-url]\n[![semantic-release][semantic-image] ][semantic-url]\n[![manpm](https://img.shields.io/badge/manpm-%E2%9C%93-3399ff.svg)](https://github.com/bahmutov/manpm)\n\n## Why\n\nCSRF tokens are a good security practice. A login form page contains a hidden input\nfield that is sent together with the username / password pair. The server checks if\nthe sent data contains the valid CSRF field before trying to authenticate the user.\n\n    \u003cform method=\"POST\" action=\"/login/\" id=\"loginform\"\u003e\n        \u003cinput type=\"hidden\" name=\"csrfmiddlewaretoken\" value=\"\u003clong random hash\u003e\"\" /\u003e\n        \u003cinput type=\"email\" name=\"email\" /\u003e\n        \u003cinput type=\"password\" name=\"password\" /\u003e\n    \u003c/form\u003e\n\nThere are two components to the protection: the hidden input value and a cookie. In order to\nsuccessfully execute requests, for example the login POST, one needs to fetch the login page,\ngrab the middleware token and use it to form the valid POST request, plus use the same value\nas a cookie when making the POST request!\n\n**csrf-login** allows you to login from command line to websites that use CSRF token protection.\n\n## Install and use\n\nInstall and use under Node\n\n    npm install csrf-login --save\n\nCreate a new file `csrf.json` in the current working folder, place the following custom parameters\ninto this configuration file. For example,\n\n```json\n{\n  \"host\": \"http://my-dev-server:3000\",\n  \"loginFormId\": \"loginform\",\n  \"tokenFieldName\": \"csrfmiddlewaretoken\",\n  \"loginPath\": \"/accounts/login/\"\n}\n```\n\nYou can take a look at the defaults in [src/defaults.json](src/defaults.json)\n\nFrom your code use the function\n\n```js\nvar csrfLogin = require('csrf-login');\ncsrfLogin({\n    username: username,\n    password: password\n}).then(function (info) {\n  // info = { request, requestAsync, response, conf };\n  return info.requestAsync('/api/foo', { some: params });\n}).then(function (data) { });\n```\n\nTo get username and password from the user, you can use\n[get-username-and-password](https://github.com/bahmutov/get-username-and-password).\n\n## Passing options\n\nInstead of a JSON file, you can pass options as an object\n\n```js\nvar csrfLogin = require('csrf-login');\ncsrfLogin({\n  host: 'https://server.com',\n  username: username,\n  password: password\n})\n```\n\nYou can also pass folder with the config file, for example if the\n`csrf.json` file is in the same as the caller source file. The options\nfrom the loaded file will combined with additional options.\n\n```js\nvar csrfLogin = require('csrf-login');\ncsrfLogin({\n  folder: __dirname,\n  password: password\n})\n```\n\nYou can also pass options via environment variables\n\n```sh\nUSERNAME=me PASSWORD=test123 npm test\n```\n\n## Returned object\n\nThe returned object `info` has several properties\n\n```js\ncsrfLogin(user)\n  .then(function (info) {\n    console.log(Object.keys(info))\n    // [ 'request', 'requestAsync', 'response', 'config', 'jar' ]\n  })\n```\n\n### info.response\n\nThis is the response object from the login call\n\n### info.request\n\nThe [request](https://www.npmjs.com/package/request) function you can use\nto execute other API calls (the session cookie is set for example)\n\n```js\ncsrfLogin()\n  .then(function (info) {\n    info.request('/some/other/end/point', function (error, response, body) {\n      //Act on the response...\n    });\n  });\n```\n\nIf you want to use promises instead of callbacks, use the `requestAsync` property\n\n### info.requestAsync\n\nThe same [request](https://www.npmjs.com/package/request) object, but wrapped\nin a promise-returning function. For example to make another API JSON request\n\n```js\ncsrfLogin()\n  .then(function (info) {\n    return info.requestAsync({\n      url: '/some/data/api',\n      json: true\n    });\n  })\n  .then(function (data) {\n    console.log('got data from /some/data/api');\n    console.log(data);\n  })\n  .catch(onError)\n  .done();\n```\n\n### info.config\n\nThe full configuration object, created from `csrf.json`, environment and\ncommand line arguments. Uses [nconf](https://www.npmjs.com/package/nconf). One\ncan get the `host` for example\n\n```js\ncsrfLogin()\n  .then(function (info) {\n    console.log('logged into', info.get('host'));\n  });\n```\n\n### info.jar\n\nThe [cookie jar](https://www.npmjs.com/package/request#examples) after the login.\nWill contain session / auth cookies for requests.\n\n## Debugging\n\nIf you need to debug the login process, run the module with debug logging option\n\n    DEBUG=csrf node client.js\n\nUnder the hood, csrf-login is using [request](https://www.npmjs.com/package/request)\nmodule, and you can enable the request debug logging\n\n    DEBUG=csrf NODE_DEBUG=request node client.js\n\nThere is a scrip [demo/demo.js](demo/demo.js) you can use to quickly test the login\nfeature.\n\n## Optional Configuration\n\nBy default, a form is looked up by Id and the submitted login form fields are expected to be named `email` and `password`. You can override these defaults in the config using the `loginFormSelector`, `loginUsernameField`, and `loginPasswordField`.\n\n```js\n{\n  \"host\": \"http://my-dev-server:3000\",\n  \"loginFormSelector\": \"class='myForm'\",\n  \"loginUsernameField\": \"username\",\n  \"loginPasswordField\": \"userPassword\",\n  \"tokenFieldName\": \"csrfmiddlewaretoken\",\n  \"loginPath\": \"/accounts/login/\"\n}\n```\n\n## Demo\n\nI have coded a small demo server, you can start it manually using `npm run demo-server`\nthen open `localhost:3000`, `localhost:3000/login` pages. You can also run unit tests against\nthe demo server and see how the token is captured and used in the unit tests using\n`npm run demo-test` command.\n\n## Small print\n\nAuthor: Gleb Bahmutov \u0026copy; 2015\n\n* [@bahmutov](https://twitter.com/bahmutov)\n* [glebbahmutov.com](http://glebbahmutov.com)\n* [blog](http://glebbahmutov.com/blog/)\n\nLicense: MIT - do anything with the code, but don't blame me if it does not work.\n\nSpread the word: tweet, star on github, etc.\n\nSupport: if you find any problems with this module, email / tweet /\n[open issue](https://github.com/bahmutov/csrf-login/issues) on Github\n\n## MIT License\n\nCopyright (c) 2015 Gleb Bahmutov\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n[csrf-login-icon]: https://nodei.co/npm/csrf-login.png?downloads=true\n[csrf-login-url]: https://npmjs.org/package/csrf-login\n[csrf-login-ci-image]: https://travis-ci.org/bahmutov/csrf-login.png?branch=master\n[csrf-login-ci-url]: https://travis-ci.org/bahmutov/csrf-login\n[csrf-login-dependencies-image]: https://david-dm.org/bahmutov/csrf-login.png\n[csrf-login-dependencies-url]: https://david-dm.org/bahmutov/csrf-login\n[csrf-login-devdependencies-image]: https://david-dm.org/bahmutov/csrf-login/dev-status.png\n[csrf-login-devdependencies-url]: https://david-dm.org/bahmutov/csrf-login#info=devDependencies\n[semantic-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg\n[semantic-url]: https://github.com/semantic-release/semantic-release\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahmutov%2Fcsrf-login","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbahmutov%2Fcsrf-login","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahmutov%2Fcsrf-login/lists"}