UNPKG

superlogin

Version:

Powerful authentication for APIs and single page apps using the CouchDB ecosystem which supports a variety of providers.

445 lines (415 loc) 14.4 kB
'use strict'; var request = require('superagent'); var expect= require('chai').expect; var BPromise = require('bluebird'); global.Promise = BPromise; var PouchDB = require('pouchdb'); var seed = require('pouchdb-seed-design'); var util = require('../lib/util.js'); describe('SuperLogin', function() { var app; var superlogin; var userDB, keysDB; var previous; var accessToken; var accessPass; var expireCompare; var config = require('./test.config'); var server = 'http://localhost:5000'; var dbUrl = util.getDBURL(config.dbServer); var newUser = { name: 'Kewl Uzer', username: 'kewluzer', email: 'kewluzer@example.com', password: '1s3cret', confirmPassword: '1s3cret' }; var newUser2 = { name: 'Kewler Uzer', username: 'kewleruzer', email: 'kewleruzer@example.com', password: '1s3cret', confirmPassword: '1s3cret' }; before(function() { userDB = new PouchDB(dbUrl + "/sl_test-users"); keysDB = new PouchDB(dbUrl + "/sl_test-keys"); app = require('./test-server')(config); app.superlogin.onCreate(function(userDoc, provider) { userDoc.profile = {name: userDoc.name}; return BPromise.resolve(userDoc); }); previous = seed(userDB, require('../designDocs/user-design')); return previous; }); after(function() { return previous .then(function() { return BPromise.all([userDB.destroy(), keysDB.destroy()]); }) .then(function() { // console.log('DBs Destroyed'); app.shutdown(); }); }); it('should create a new user', function() { return previous.then(function() { return new BPromise(function(resolve, reject) { request .post(server + '/auth/register') .send(newUser) .end(function(err, res) { if (err) return reject(err); expect(res.status).to.equal(201); expect(res.body.success).to.equal('User created.'); // console.log('User created'); resolve(); }); }); }); }); it('should verify the email', function() { var emailToken; return previous.then(function() { return userDB.get('kewluzer') .then(function(record) { emailToken = record.unverifiedEmail.token; return 1; }) .then(function() { return new BPromise(function(resolve, reject) { request .get(server + '/auth/confirm-email/' + emailToken) .end(function(err, res) { if (err) return reject(err); expect(res.status).to.equal(200); // console.log('Email successfully verified.'); resolve(); }); }); }); }); }); it('should login the user', function() { return previous.then(function() { return new BPromise(function(resolve, reject) { request .post(server + '/auth/login') .send({ username: newUser.username, password: newUser.password }) .end(function(err, res) { if (err) return reject(err); accessToken = res.body.token; accessPass = res.body.password; expect(res.status).to.equal(200); expect(res.body.roles[0]).to.equal('user'); expect(res.body.token.length).to.be.above(10); expect(res.body.profile.name).to.equal(newUser.name); // console.log('User successfully logged in'); resolve(); }); }); }); }); it('should access a protected endpoint', function() { return previous.then(function() { return new BPromise(function(resolve, reject) { request .get(server + '/auth/session') .set('Authorization', 'Bearer ' + accessToken + ':' + accessPass) .end(function(err, res) { if (err) return reject(err); expect(res.status).to.equal(200); // console.log('Secure endpoint successfully accessed.'); resolve(); }); }); }); }); it('should require a role', function() { return previous.then(function() { return new BPromise(function(resolve, reject) { request .get(server + '/user') .set('Authorization', 'Bearer ' + accessToken + ':' + accessPass) .end(function(err, res) { if (err) return reject(err); expect(res.status).to.equal(200); // console.log('Role successfully required.'); resolve(); }); }); }); }); it('should deny access when a required role is not present', function() { return previous.then(function() { return new BPromise(function(resolve, reject) { request .get(server + '/admin') .set('Authorization', 'Bearer ' + accessToken + ':' + accessPass) .end(function(err, res) { //if (err) return reject(err); expect(res.status).to.equal(403); // console.log('Admin access successfully denied.'); resolve(); }); }); }); }); it('should generate a forgot password token', function() { return previous.then(function() { return new BPromise(function(resolve, reject) { request .post(server + '/auth/forgot-password') .send({email: newUser.email}) .end(function(err, res) { if (err) return reject(err); expect(res.status).to.equal(200); // console.log('Password token successfully generated.'); resolve(); }); }); }); }); it('should reset the password', function() { return previous.then(function() { return userDB.get(newUser.username) .then(function(resetUser) { var resetToken = resetUser.forgotPassword.token; return new BPromise(function(resolve, reject) { request .post(server + '/auth/password-reset') .send({token: resetToken, password: 'newpass', confirmPassword: 'newpass'}) .end(function(error, res) { if(error || res.status !== 200) { throw new Error('Failed to reset the password.'); } expect(res.status).to.equal(200); // console.log('Password successfully reset.'); resolve(); }); }); }); }); }); it('should logout the user upon password reset', function() { return previous.then(function() { return new BPromise(function(resolve, reject) { request .get(server + '/auth/session') .set('Authorization', 'Bearer ' + accessToken + ':' + accessPass) .end(function(err, res) { //if (err) return reject(err); expect(res.status).to.equal(401); // console.log('User has been successfully logged out on password reset.'); resolve(); }); }); }); }); it('should login with the new password', function() { return previous.then(function() { return new BPromise(function(resolve, reject) { request .post(server + '/auth/login') .send({ username: newUser.username, password: 'newpass' }) .end(function(err, res) { if (err) return reject('Failed to log in. ' + err); accessToken = res.body.token; accessPass = res.body.password; expireCompare = res.body.expires; expect(res.status).to.equal(200); expect(res.body.roles[0]).to.equal('user'); expect(res.body.token.length).to.be.above(10); // console.log('User successfully logged in with new password'); resolve(); }); }); }); }); it('should refresh the session', function() { return previous.then(function() { return new BPromise(function(resolve, reject) { request .post(server + '/auth/refresh') .set('Authorization', 'Bearer ' + accessToken + ':' + accessPass) .end(function(err, res) { if (err) return reject(err); expect(res.status).to.equal(200); expect(res.body.expires).to.be.above(expireCompare); // console.log('Session successfully refreshed.'); resolve(); }); }); }); }); it('should change the password', function() { return previous.then(function() { return userDB.get(newUser.username) .then(function(resetUser) { return new BPromise(function(resolve, reject) { request .post(server + '/auth/password-change') .set('Authorization', 'Bearer ' + accessToken + ':' + accessPass) .send({currentPassword: 'newpass', newPassword: 'newpass2', confirmPassword: 'newpass2'}) .end(function(error, res) { if(error || res.status !== 200) { throw new Error('Failed to change the password.'); } expect(res.status).to.equal(200); // console.log('Password successfully changed.'); resolve(); }); }); }); }); }); it('should logout the user', function() { return previous .then(function() { return new BPromise(function(resolve, reject) { request .post(server + '/auth/logout') .set('Authorization', 'Bearer ' + accessToken + ':' + accessPass) .end(function(error, res) { if(error || res.status !== 200) { throw new Error('Failed to logout the user.'); } expect(res.status).to.equal(200); resolve(); }); }) .then(function() { return new BPromise(function(resolve, reject) { request .get(server + '/auth/session') .set('Authorization', 'Bearer ' + accessToken + ':' + accessPass) .end(function(error, res) { expect(res.status).to.equal(401); // console.log('User has been successfully logged out.'); resolve(); }); }); }); }); }); it('should login after creating a new user', function() { return previous.then(function() { app.config.setItem('security.loginOnRegistration', true); return new BPromise(function(resolve, reject) { request .post(server + '/auth/register') .send(newUser2) .end(function(error, res) { expect(res.status).to.equal(200); /* jshint -W030 */ expect(res.body.token).to.be.a.string; /* jshint +W030 */ // console.log('User created and logged in'); resolve(); }); }); }); }); it('should validate a username', function() { return previous .then(function() { return new BPromise(function(resolve, reject) { request .get(server + '/auth/validate-username/idontexist') .end(function(error, res) { expect(res.status).to.equal(200); expect(res.body.ok).to.equal(true); resolve(); }); }); }) .then(function() { return new BPromise(function(resolve, reject) { request .get(server + '/auth/validate-username/kewluzer') .end(function(error, res) { expect(res.status).to.equal(409); // console.log('Validate Username is working'); resolve(); }); }); }); }); it('should validate an email', function() { return previous .then(function() { return new BPromise(function(resolve, reject) { request .get(server + '/auth/validate-email/nobody@example.com') .end(function(error, res) { expect(res.status).to.equal(200); expect(res.body.ok).to.equal(true); resolve(); }); }); }) .then(function() { return new BPromise(function(resolve, reject) { request .get(server + '/auth/validate-username/kewluzer@example.com') .end(function(error, res) { expect(res.status).to.equal(409); // console.log('Validate Email is working'); resolve(); }); }); }); }); function attemptLogin(username, password) { return new BPromise(function(resolve, reject) { request .post(server + '/auth/login') .send({ username: username, password: password }) .end(function(error, res) { resolve({status: res.status, message: res.body.message}); }); }); } it('should respond unauthorized if a user logs in and no password is set', function() { return previous .then(function() { return userDB.put({ _id: 'nopassword', email: 'nopassword@example.com' }); }) .then(function() { return attemptLogin('nopassword', 'wrongpassword'); }) .then(function(result) { expect(result.status).to.equal(401); expect(result.message).to.equal('Invalid username or password'); }); }); it('should block a user after failed logins', function() { return previous .then(function() { return attemptLogin('kewluzer', 'wrong'); }) .then(function(result) { expect(result.status).to.equal(401); expect(result.message).to.equal('Invalid username or password'); return attemptLogin('kewluzer', 'wrong'); }) .then(function(result) { expect(result.status).to.equal(401); expect(result.message).to.equal('Invalid username or password'); return attemptLogin('kewluzer', 'wrong'); }) .then(function(result) { expect(result.status).to.equal(401); expect(result.message.search('Maximum failed login')).to.equal(0); return attemptLogin('kewluzer', 'newpass'); }) .then(function(result) { expect(result.status).to.equal(401); expect(result.message.search('Your account is currently locked')).to.equal(0); return BPromise.resolve(); }); }); });