Skip to content

Commit

Permalink
Assignment6
Browse files Browse the repository at this point in the history
* build ./authenticate and ./private points.
* use prerequisite extensions to execute authentication logic.
* Make simple database.js data store to authenticate user records with.
* Apply default authStrategy to ./private point.
* No authStrategy for ./authenticate point.
  • Loading branch information
zoe-1 committed Jan 11, 2018
1 parent 036ac9a commit 739aec8
Show file tree
Hide file tree
Showing 7 changed files with 200 additions and 3 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ language: node_js

node_js:
- "8"
- "9"

sudo: false
4 changes: 2 additions & 2 deletions lib/authtoken.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ const internals = {};

const defaultValidateFunc = (request, token) => {

// Put database query to authenticate the token is valid here.
// Uses catbox policy for token authentication here (lesson7 or 8).

return {
isValid: token === '12345678',
credentials: { token }
credentials: { token, username: 'foofoo', scope: ['admin'] } // scope set in credentials.
};
};

Expand Down
49 changes: 49 additions & 0 deletions lib/database.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use strict';

// mock user database

const internals = {};

internals.db = [
{
'id': 1,
'username': 'foofoo',
'password': '12345678',
'email': 'foo@hapiu.com',
'scope': ['admin', 'user']
},
{
'id': 2,
'username': 'barica',
'password': 'bar',
'email': 'bar@hapiu.com',
'scope': ['user']
}
];

exports.authenticate = (username, password) => {

for (const userRecord of internals.db) {

if (userRecord.username === username) {

// valid username

if (userRecord.password === password) {

delete userRecord.password;

// authentic user credentials

const authenticUserRecord = { authentic: true, userRecord };
return authenticUserRecord;
}

const authenticUserRecord = { authentic: false, userRecord: null };
return authenticUserRecord;
}
}

const authenticUserRecord = { authentic: false, userRecord: null };
return authenticUserRecord;
};
73 changes: 73 additions & 0 deletions lib/version.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use strict';

const Package = require('../package.json');
const Database = require('./database');
const Boom = require('boom');

// Declare internals

Expand All @@ -14,6 +16,10 @@ exports.plugin = {
// Use below to test requests to the live server.
// curl -H "Authorization: Bearer 12345678" -X GET http://localhost:8000/version

//
// ./version
//

const version = function (request, h) {

return 'version ' + Package.version + ' ' + options.message;
Expand All @@ -28,5 +34,72 @@ exports.plugin = {
handler: version
}
});

//
// ./authenticate
//

const authenticate = function (request, h) {

// console.log('DEV LOG request.pre.welcome: ' + JSON.stringify(request.pre.welcome, 0, 2));

if (request.pre.welcome.message === 'welcome') {

// return JSON.stringify(request.pre.welcome);
return request.pre.welcome;
}

return Boom.unauthorized('invalid credentials');
};

const authenticateUserStep = function (request, h) {

const result = Database.authenticate(request.payload.username, request.payload.password);

if (result.authentic === true) {

// @todo set cache records here (catbox-redis) lesson7.
// @todo prempt multiple authtokens (lesson7).
// check if user already authenticated. If yes, return current authtoken.
// @todo generate token here (cryptiles) lesson8.

const welcome = { message: 'welcome', token: '12345678' };
return welcome;
}

return 'invalid user';
};


server.route({
method: 'POST',
path: '/authenticate',
config: {
description: 'Authenticates user credentials & returns token.',
auth: false,
handler: authenticate,
pre: [{ method: authenticateUserStep, assign: 'welcome' }]
}
});
// curl -H "Content-Type: application/json" -X POST -d '{"username":"foofoo","password":"12345678"}' https://localhost:8000/authenticate

//
// ./private
//

const privateHandle = function (request, h) {

return 'privateData';
};

server.route({
method: 'GET',
path: '/private',
config: {
description: 'private data for authenticated `admin` users.',
auth: { strategy: 'default', scope: ['admin'] },
handler: privateHandle
}
});
}
};
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
},
"homepage": "https://github.com/zoe-1/university-rewrite#readme",
"dependencies": {
"boom": "^7.1.1",
"hapi": "17.x.x",
"hapi-auth-bearer-token": "6.x.x"
},
Expand Down
73 changes: 73 additions & 0 deletions test/version.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,77 @@ describe('/version', () => {
expect(res.result).to.equal('version 1.0.5 lesson5');
await server.stop();
});

it('succesfully authenticates', { parallel: false }, async () => {

const University = require('../lib');

const server = await University.init(internals.serverOptions);

expect(server).to.be.an.object();

// curl -H "Content-Type: application/json" -X POST -d '{"username":"foofoo","password":"12345678"}' https://localhost:8000/authenticate

const request = { method: 'POST', url: '/authenticate', payload: { username: 'foofoo', password: '12345678' } };

const res = await server.inject(request);

expect(res.result.message).to.equal('welcome');
expect(res.result.token.length).to.equal(8);
await server.stop();
});

it('fails to authenticate, bad password', { parallel: false }, async () => {

const University = require('../lib');

const server = await University.init(internals.serverOptions);

expect(server).to.be.an.object();

const request = { method: 'POST', url: '/authenticate', payload: { username: 'foofoo', password: '123478' } };

const res = await server.inject(request);

expect(res.result.statusCode).to.equal(401);
expect(res.result.message).to.equal('invalid credentials');
await server.stop();
});

it('fails to authenticate, bad username', { parallel: false }, async () => {

const University = require('../lib');

const server = await University.init(internals.serverOptions);

expect(server).to.be.an.object();

const request = { method: 'POST', url: '/authenticate', payload: { username: 'tootoo', password: '123478' } };

const res = await server.inject(request);

expect(res.result.statusCode).to.equal(401);
expect(res.result.message).to.equal('invalid credentials');
await server.stop();
});

it('successfully access private data', async () => {

const University = require('../lib');

const server = await University.init(internals.serverOptions);

expect(server).to.be.an.object();

// curl -k -X GET -H "Authorization: Bearer 12345678" https://localhost:8000/version

const request = { method: 'GET', url: '/private', headers: { authorization: 'Bearer 12345678' } };

const res = await server.inject(request);

expect(res.result).to.equal('privateData');
await server.stop();
});
});


0 comments on commit 739aec8

Please sign in to comment.