Skip to content

Commit

Permalink
Fix/authentication (#5)
Browse files Browse the repository at this point in the history
* Add mock API Gateway related code

- Copy from sbr-ui fix/authentication

* Migrate sbr-ui fix/authentication code to bi-ui

- Remove unused dependancies (jwt)
- Fix LoginActions/auth.js to mimick sbr-ui
- Add base64 encoding to LoginActions
- Use base64 for encoding username:password rather than bcrypt in the mock gateway
- Fix saving of accessToken in sessionStorage

* Fix rerouting of API requests to work for bi

- Change URL to localhost:9000 (business-index-api)
  • Loading branch information
ONS-Tom authored and ONS-Anthony committed Oct 26, 2017
1 parent bdad45c commit 01b5842
Show file tree
Hide file tree
Showing 14 changed files with 426 additions and 124 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,11 @@
"express": "^4.14.0",
"halogen": "^0.2.0",
"ie-version": "^0.1.0",
"request-promise": "^4.2.2",
"istanbul": "^0.4.5",
"jasmine": "^2.5.3",
"jasmine-node": "^1.14.5",
"jquery": "^3.2.1",
"jsonwebtoken": "^7.1.9",
"jwt-decode": "^2.2.0",
"loadtest": "^2.3.0",
"memory-cache": "^0.2.0",
"morgan": "^1.7.0",
Expand Down Expand Up @@ -85,6 +84,7 @@
"redux-thunk": "^2.2.0",
"registers-react-library": "^1.0.0",
"request": "^2.81.0",
"uuid": "^3.1.0",
"winston": "^2.4.0"
},
"engines": {
Expand Down
138 changes: 138 additions & 0 deletions server/apiGateway.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
'use strict';

/* eslint strict: "off" */
/* eslint no-console: "off" */
/* eslint comma-dangle: ["error", "never"] */

const express = require('express');
const morgan = require('morgan');
const myParser = require('body-parser');
const base64 = require('base-64');
const compression = require('compression');
const rp = require('request-promise');
const timeouts = require('./config/timeouts');
const urls = require('./config/urls');
const uuidv4 = require('uuid/v4');
const logger = require('./logger');

const PORT = process.env.PORT || 3002;

// Get the admin/user credentials from environment variables
const ADMIN_USERNAME = process.env.BI_UI_TEST_ADMIN_USERNAME;
const ADMIN_PASSWORD = process.env.BI_UI_TEST_ADMIN_PASSWORD;
const USER_USERNAME = process.env.BI_UI_TEST_USER_USERNAME;
const USER_PASSWORD = process.env.BI_UI_TEST_USER_PASSWORD;

// We use the users JSON as a mock database holding { username: hashed_password }
const users = {};
users[ADMIN_USERNAME] = `Basic ${base64.encode(`${ADMIN_USERNAME}:${ADMIN_PASSWORD}`)}`;
users[USER_USERNAME] = `Basic ${base64.encode(`${USER_USERNAME}:${USER_PASSWORD}`)}`;

// We need to store all the valid API keys that uuidv4() has made
const validApiKeys = {};

const app = express();
app.use(compression()); // gzip all responses
app.use(morgan(':remote-addr - :remote-user [:date[clf]] ":method :url HTTP/:http-version" :status :res[content-length] :response-time ms'));
app.use(myParser.json()); // For parsing body of POSTs

app.post('/auth', (req, res) => {
logger.info('Checking /auth');
const username = req.body.username;
const basicAuth = req.get('Authorization');

// If the provided basic authentication matches any of our own base64 encoded
// Authorization keys in the users JSON
if (users[username] === basicAuth) {
logger.info('Creating API Key for user');
const key = uuidv4();
validApiKeys[key] = basicAuth;
res.setHeader('Content-Type', 'application/json');
return res.send(JSON.stringify({
key,
role: 'admin'
}));
}
return res.sendStatus(401);
});

app.get('/bi/*', (req, res) => {
const url = getUrlEndpoint(req.originalUrl);
logger.info(`Rerouting GET API request to ${url}`);

// Check if the API Key is valid
const apiKey = req.get('Authorization');
if (validApiKey(apiKey)) {
getApiEndpoint(`${urls.API_URL}${url}`)
.then((response) => {
logger.info('Returning re-routed GET API request');
return res.send(response);
})
.catch((error) => {
logger.error('Error rerouting GET request');
return res.status(error.statusCode).send(error);
});
} else {
return res.sendStatus(401);
}
});

app.post('/bi/*', (req, res) => {
const url = getUrlEndpoint(req.originalUrl);
logger.info(`Rerouting POST API request to ${url}`);

// Check if the API Key is valid
const apiKey = req.get('Authorization');
if (validApiKey(apiKey)) {
const postBody = req.body;
postApiEndpoint(`${urls.API_URL}${url}`, postBody)
.then((response) => {
logger.info('Returning re-routed POST API request');
return res.send(response);
})
.catch((error) => {
logger.error('Error rerouting POST request');
return res.status(error.statusCode).send(error);
});
} else {
return res.sendStatus(401);
}
});

function validApiKey(apiKey) {
return validApiKeys[apiKey];
}

function getUrlEndpoint(url) {
return url.substring(url.indexOf('/', 1), url.length);
}

function getApiEndpoint(url) {
logger.debug(`GET API endpoint for ${url}`);
const options = {
method: 'GET',
uri: url,
timeout: timeouts.API_GET
};

return rp(options);
}

function postApiEndpoint(url, postBody) {
logger.debug(`POST API endpoint for ${url}`);
const options = {
method: 'POST',
uri: url,
timeout: timeouts.API_POST,
headers: { 'Content-Type': 'text/plain;charset=UTF-8' },
body: JSON.stringify(postBody), // '{"updatedBy":"name","vars":{"ent_name":"name"}}',
json: false
};

return rp(options);
}

app.listen(PORT, () => {
console.log(`bi-ui-mock-api-gateway listening on port ${PORT}!`);
logger.info(`bi-ui-mock-api-gateway listening on port ${PORT}!`);
});
Loading

0 comments on commit 01b5842

Please sign in to comment.