csrf-login
Login from command line to the websites that use CSRF protection
!NPMcsrf-login-icon csrf-login-url
!Build statuscsrf-login-ci-image csrf-login-ci-url !dependenciescsrf-login-dependencies-image csrf-login-dependencies-url !devdependenciescsrf-login-devdependencies-image csrf-login-devdependencies-url !semantic-releasesemantic-image semantic-url
Why
CSRF tokens are a good security practice. A login form page contains a hidden input field that is sent together with the username / password pair. The server checks if the sent data contains the valid CSRF field before trying to authenticate the user.<form method="POST" action="/login/" id="loginform">
<input type="hidden" name="csrfmiddlewaretoken" value="<long random hash>"" />
<input type="email" name="email" />
<input type="password" name="password" />
</form>
There are two components to the protection: the hidden input value and a cookie. In order to
successfully execute requests, for example the login POST, one needs to fetch the login page,
grab the middleware token and use it to form the valid POST request, plus use the same value
as a cookie when making the POST request!csrf-login allows you to login from command line to websites that use CSRF token protection.
Install and use
Install and use under Nodenpm install csrf-login --save
Create a new file csrf.json
in the current working folder, place the following custom parameters
into this configuration file. For example,{
"host": "http://my-dev-server:3000",
"loginFormId": "loginform",
"tokenFieldName": "csrfmiddlewaretoken",
"loginPath": "/accounts/login/"
}
You can take a look at the defaults in src/defaults.json
From your code use the function
var csrfLogin = require('csrf-login');
csrfLogin({
username: username,
password: password
}).then(function (info) {
// info = { request, requestAsync, response, conf };
return info.requestAsync('/api/foo', { some: params });
}).then(function (data) { });
To get username and password from the user, you can use get-username-and-password.
Passing options
Instead of a JSON file, you can pass options as an objectvar csrfLogin = require('csrf-login');
csrfLogin({
host: 'https://server.com',
username: username,
password: password
})
You can also pass folder with the config file, for example if the
csrf.json
file is in the same as the caller source file. The options
from the loaded file will combined with additional options.var csrfLogin = require('csrf-login');
csrfLogin({
folder: __dirname,
password: password
})
You can also pass options via environment variables
USERNAME=me PASSWORD=test123 npm test
Returned object
The returned objectinfo
has several propertiescsrfLogin(user)
.then(function (info) {
console.log(Object.keys(info))
// [ 'request', 'requestAsync', 'response', 'config', 'jar' ]
})
info.response
This is the response object from the login callinfo.request
The request function you can use to execute other API calls (the session cookie is set for example)csrfLogin()
.then(function (info) {
info.request('/some/other/end/point', function (error, response, body) {
//Act on the response...
});
});
If you want to use promises instead of callbacks, use the
requestAsync
propertyinfo.requestAsync
The same request object, but wrapped in a promise-returning function. For example to make another API JSON requestcsrfLogin()
.then(function (info) {
return info.requestAsync({
url: '/some/data/api',
json: true
});
})
.then(function (data) {
console.log('got data from /some/data/api');
console.log(data);
})
.catch(onError)
.done();
info.config
The full configuration object, created fromcsrf.json
, environment and
command line arguments. Uses nconf. One
can get the host
for examplecsrfLogin()
.then(function (info) {
console.log('logged into', info.get('host'));
});
info.jar
The cookie jar after the login. Will contain session / auth cookies for requests.Debugging
If you need to debug the login process, run the module with debug logging optionDEBUG=csrf node client.js
Under the hood, csrf-login is using request
module, and you can enable the request debug loggingDEBUG=csrf NODE_DEBUG=request node client.js
There is a scrip demo/demo.js you can use to quickly test the login
feature.Optional Configuration
By default, a form is looked up by Id and the submitted login form fields are expected to be namedemail
and password
. You can override these defaults in the config using the loginFormSelector
, loginUsernameField
, and loginPasswordField
.{
"host": "http://my-dev-server:3000",
"loginFormSelector": "class='myForm'",
"loginUsernameField": "username",
"loginPasswordField": "userPassword",
"tokenFieldName": "csrfmiddlewaretoken",
"loginPath": "/accounts/login/"
}
Demo
I have coded a small demo server, you can start it manually usingnpm run demo-server
then open localhost:3000
, localhost:3000/login
pages. You can also run unit tests against
the demo server and see how the token is captured and used in the unit tests using
npm run demo-test
command.Small print
Author: Gleb Bahmutov © 2015License: MIT - do anything with the code, but don't blame me if it does not work.
Spread the word: tweet, star on github, etc.
Support: if you find any problems with this module, email / tweet / open issue on Github
MIT License
Copyright (c) 2015 Gleb BahmutovPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.