Make a NodeJs application private on Heroku - node.js

I'm trying to make a NodeJS application on Heroku private so that only developers can see it. Is there a simply way to do that, like basic auth? (All of the solutions I keep finding are specific to Ruby apps).

If you want to leverage basic authentication, here are two options: http-auth and Passport. http-auth is a very simple module and Passport is a powerful module with alternatives for authentication. Both modules provide code examples ranging from basic code to Express framework integration.

I have the same problem. I managed to get one solution working that may work for you but wasn't suitable for me as it seems to interfere with the built in user login from angular-fullstack.
I just wanted a quick way to password protect the app so that only developers and stakeholders could see it. https://www.npmjs.org/package/http-auth seems to do the trick.
This involves add http-auth to your project (npm install http-auth --save). Then you'll need to find the file where your createServer is defined and the code there.
If you're using Express you can do something like this
// HTTP Authentication
var preAuth = require('http-auth');
var basic = preAuth.basic({
realm: "Restricted Access! Please login to proceed"
}, function (username, password, callback) {
callback( (username === "user" && password === "password"));
}
);
// Setup server
var app = express();
app.use(preAuth.connect(basic));
var server = require('http').createServer(app);
If not then you can try one of the options from the http-auth documentation e.g.
// Authentication module.
var auth = require('http-auth');
var basic = auth.basic({
realm: "Simon Area."
}, function (username, password, callback) { // Custom authentication method.
callback(username === "Tina" && password === "Bullock");
}
);
// Creating new HTTP server.
http.createServer(basic, function(req, res) {
res.end("Welcome to private area - " + req.user + "!");
}).listen(1337);
Here are also a couple of related threads with somewhat similar approaches.
express.basicAuth throwing error
Basic HTTP authentication in Node.JS?

Related

Mocking different passport.js strategies in an integration test

In the /config/passport.js file I've defined and am using different strategies:
var
sails = require('sails'),
passport = require('passport'),
LocalStrategy = require('passport-local').Strategy,
CustomStrategy = require('passport-custom').Strategy,
GoogleStrategy = require('passport-google-oauth').OAuth2Strategy,
FacebookStrategy = require('passport-facebook').Strategy;
passport.use(new LocalStrategy({...}, function(email, password, done){...}));
passport.use('my-custom-strategy', new CustomStrategy(function (req, done){...}));
... same for FB and Google
And I want to do an integration test, where I mock the result returned to the controller from these strategies (and focus on the rest of the controller and service processing). Specifically, mocking the custom-strategy is important for me.
I could find some scarce examples like this post and the followup link, but could not relate that much to my use cases.
Can anyone give me some code examples that I can start building my tests from?
var expect = require('chai').expect
, request = require('supertest')
, sinon = require('sinon')
, passport = require('passport');
describe('/auth', function () {
it('should return correct authentication response with tokens', function (done) {
// here I want to mock the custom strategy (or any other)
var requestBody = {
// some info
};
request(url)
.post('/auth')
.send(requestBody)
.end(function (err, res) {
if (err) {
return done(err);
}
console.log(res.body);
done();
});
});
});
To me from your question it is not clear exactly what functions you want to mock.
I would interpret two problem scenarios here:
Either you want to mock the authentication itself, f.e. to test API controllers relying on an authenticated user. For this scenario the provided links are one possible way. Just write another authentication mechanism which fakes a logged in user. The mock strategy would not go through all the code than a real strategy would but just does the minimum what needs to be done. Maybe also manipulation the database if needed. There is nothing much to be added here if your question is not more specific.
The other scenario is that you want to test the strategy itself. So you want to mock external i/o which your strategy relies on. This can be user input / http traffic and/or database interaction. Since user input usually is collected on the server using http traffic and lots of strategies use external servers to authenticate I would suggest to mock the actual http traffic the way you need it to test your strategy. You can do this using nock. For the database interactions you could f.e. setup a testing db.

Retrieving data from Pocket API (oAuth)

I need to retrieve my saved reading list from my Pocket account
and it seems that I need to acquire access token through their oAuth to make a request.
I've got consumer key for the access token and as per Pocket API documentation, the request will resemble something like this.
POST /v3/oauth/request HTTP/1.1
Host: getpocket.com
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Accept: application/x-www-form-urlencoded
consumer_key=1234-abcd1234abcd1234abcd1234&
redirect_uri=pocketapp1234:authorizationFinished
My question is... isn't oAuth for 3rd party apps to enable authentication via Google, Facebook account? I don't see how this idea is relevant for my website that will only require access to my own data from Pocket to share on my site.
I understand I will need to authenticate somehow so I can access my data but is oAuth the process I will need to go through to get what I need?
It seems that they support only 3 legged OAuth flow. You can use Grant in your NodeJS app, or just get access token from here.
Grant
save the following example to a file
set your key here: key:'...'
install the needed dependencies
run the file with node.js
navigate to http://localhost:3000/connect/getpocket
follow the instructions on screen
At the end you'll see your access_token.
var express = require('express')
, session = require('express-session')
var options = {
server: {protocol:'http', host:'localhost:3000'},
getpocket: {key:'...', callback:'/getpocket_callback'}
}
var Grant = require('grant-express')
, grant = new Grant(options)
var app = express()
app.use(session({secret:'very secret'}))
app.use(grant)
app.get('/getpocket_callback', function (req, res) {
console.log(req.query)
res.end(JSON.stringify(req.query, null, 2))
})
app.listen(3000, function () {
console.log('Express server listening on port ' + 3000)
})
}
Purest
Then you can use Purest to make requests to the Pocket's REST API.
var getpocket = new Purest({provider: 'getpocket'})
getpocket.query()
.post('get')
.auth('[API_KEY]', '[ACCESS_TOKEN]')
.request(function (err, res, body) {
// body is the parsed JSON response
})
For anyone reading this in 2021 or later, wanting to make a simple script to add articles to their pocket, I came up with this:
1: get your consumer key, via pocket's site.
2: get you access token, using this tool it's very simple. If you want to make an app or something that'll work without it, I guess the above (old) answer might work, didn't test it.
3: Use the following code to add an article:
var request = require('request');
request.post({
url: 'https://getpocket.com/v3/add',
form: {
url: 'https://articleToAdd.com',
consumer_key: '123456-12abcd1234a1ab12a12abc12',
access_token: '12345a1a-1ab1-1a12-12a1-1a1234'
}
},
function(err, httpResponse, body) { console.log(httpResponse.body) }
)
Hope it helps someone that is looking to do the same. Retrieving/modifying articles is similar, look here for the specifics.

Passport authentication strageties with Grunt

Question concerns setting up the development environment (later on other environment like production)....
Using latest of Node, Passport, and Grunt but Express still in the 3 chain.
Working on an application leveraging external authentication only (i.e. no local Passport strategy). The oauth client id, secret key and callback configuration per strategy (i.e. Google, Facebook etc.) is nothing (obviously) to be housed in Git.
Wondering how people tackle this with different environments? Just getting my feet wet with Grunt so I am currently registering a task (after the initConfig which reads my package.json) that reads a authentication configuration (excepting an authentication property in package.json):
grunt.registerTask('auth', function() {
var pkg = grunt.config('pkg');
var util = require('util');
if (grunt.file.exists(pkg.authentication)) {
grunt.log.writeln(util.format('Setting up authentication with %s', pkg.authentication));
var auth = grunt.file.readJSON(pkg.authentication);
.... // move auth data into a auth.js read by the application
} else
grunt.fail.warn(util.format('%s not found (authentication property in package.json), neccessary for authentication but not managaged by Git', pkg.authentication));
});
Basically, the developer/installer is responsible for having a private (not managed by Git), local settings for authentication. Something like:
{
'googleAuth' : {
'clientID' : 'your-secret-clientID-here',
'clientSecret' : 'your-client-secret-here',
'callbackURL' : 'http://localhost:8080/auth/google/callback'
}
}
A simple copy of the JSON contents into a auth.js file put in the build directory required by the application will work.
Better way?

user authentication using socket.io

I've red this tutorial: http://howtonode.org/socket-io-auth.
It shows how to authenticate users using express and socket.io.
But is there a way to authenticate users using only socket.io without the need for express?
edit:
For session handling I use RedisStore (https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO).
Whats left is a module to create authentication cookies.
Does anyone know of a socket.io implementation I can use to create an authentication cookie like you can do with session handling?
I know this is bit old, but for future readers in addition to the approach of parsing cookie and retrieving the session from the storage (eg. passport.socketio ) you might also consider a token based approach.
In this example I use JSON Web Tokens which are pretty standard. You have to give to the client page the token, in this example imagine an authentication endpoint that returns JWT:
var jwt = require('jsonwebtoken');
// other requires
app.post('/login', function (req, res) {
// TODO: validate the actual user user
var profile = {
first_name: 'John',
last_name: 'Doe',
email: 'john#doe.com',
id: 123
};
// we are sending the profile in the token
var token = jwt.sign(profile, jwtSecret, { expiresInMinutes: 60*5 });
res.json({token: token});
});
Now, your socket.io server can be configured as follows:
var socketioJwt = require('socketio-jwt');
var sio = socketIo.listen(server);
sio.set('authorization', socketioJwt.authorize({
secret: jwtSecret,
handshake: true
}));
sio.sockets
.on('connection', function (socket) {
console.log(socket.handshake.decoded_token.email, 'has joined');
//socket.on('event');
});
The socket.io-jwt middleware expects the token in a query string, so from the client you only have to attach it when connecting:
var socket = io.connect('', {
query: 'token=' + token
});
I wrote a more detailed explanation about this method and cookies here.
Instead or wiring up authentication and session handling code manually, I'd recommend to go with a dedicated module, such as session.socket.io (but please note that this is a module that requires Express as well).
I guess (but don't know) that there were downvotes because you need some sort of session handling, and you most probably do not want to do this manually as well ;-). Hence it's a quite good idea to stick with Express here.
Nevertheless, it's an interesting question, although I can not answer on how to do it without Express.
I am quite new to node.js, just started a few days ago. and i only can answer to the first part to the question, which is user authentication without the use of express. and i also got no session-style handling yet.
the reason I am still answering to this question is to help out other people who are new to node with a more simple alternative solution for the beginning.
the solution i am currently using in my learning project (a socket.io - based chat, what else?) is using the http server for authentication.
if you can't get a valid authentication on the http server, you'll never get access to the page with the socket.io interface.
the user authentication on the http server is handled by reading out some POST data. only if the POST data is valid user data the user is allowed to move on to the chat where the socket.io interface is.

NodeJS admin backend authentication strategy

I built a simple e-commerce site for a customer based in NodeJS/Express3/MongoDB and I have some doubts about what kind of authentication strategy to implement for the backend of the site.
I have little to no knowledge in authentication/authorization and I'm a little bit lost, so I'll appreciate if you help me clear the fog a little.
Only one person, the owner is going to access it. I implemented HTTP Simple authentication in the past, but as long as I know, the credentials are sent in plain text. I would need to implement HTTPS but I'm trying to avoid that.
I though about OAuth2 but it seems overkill for a single login.
Maybe Digest fits my needs. It doesn't send the credentials in plain text as long as I know.
I also found this library that look very well:
http://passportjs.org/
What do you recommend for this scenario?
I think Passport with local strategy is good enough.
Use HTTPS is always good, and not hard in Node.js.
Read The Web Application Hacker's Handbook if you wanna go deeper.
I suggest to use HTTP Basic or Digest authentication with HTTPS, you can do that using http-auth module.
// HTTPS module
var https = require('https');
// File system module.
var fs = require('fs');
// Authentication module.
var auth = require('http-auth');
var basic = auth.basic({
realm: "Simon Area.",
file: __dirname + "/../data/users.htpasswd" // gevorg:gpass, Sarah:testpass ...
});
// HTTPS server options.
var options = {
key: fs.readFileSync(__dirname + "/../data/server.key"),
cert: fs.readFileSync(__dirname + "/../data/server.crt")
};
// Starting server.
https.createServer(basic, options, function (req, res) {
res.end("Welcome to private area - " + req.user + "!");
}).listen(1337);

Resources