From 01b5842ea3e017831ab57e6cd3c48347f08fa8a7 Mon Sep 17 00:00:00 2001 From: ONS-Tom Date: Thu, 26 Oct 2017 11:41:27 +0100 Subject: [PATCH] Fix/authentication (#5) * 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) --- package.json | 4 +- server/apiGateway.js | 138 ++++++++++++++++++++++++ server/app.js | 206 +++++++++++++++++++++++------------- server/config/timeouts.js | 7 ++ server/config/urls.js | 8 ++ server/helpers/salt.js | 27 +++++ server/index.js | 34 +++++- server/package.json | 6 +- src/actions/LoginActions.js | 23 ++-- src/config/api-urls.js | 2 +- src/reducers/login.js | 2 + src/routes.js | 8 +- src/utils/apiSearch.js | 45 ++++++-- src/utils/auth.js | 40 +++---- 14 files changed, 426 insertions(+), 124 deletions(-) create mode 100644 server/apiGateway.js create mode 100644 server/config/timeouts.js create mode 100644 server/config/urls.js create mode 100644 server/helpers/salt.js diff --git a/package.json b/package.json index 9bfae23..8e65924 100644 --- a/package.json +++ b/package.json @@ -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", @@ -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": { diff --git a/server/apiGateway.js b/server/apiGateway.js new file mode 100644 index 0000000..ab4d8a6 --- /dev/null +++ b/server/apiGateway.js @@ -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}!`); +}); diff --git a/server/app.js b/server/app.js index b7fa20a..78d0b2d 100644 --- a/server/app.js +++ b/server/app.js @@ -7,10 +7,12 @@ const express = require('express'); const morgan = require('morgan'); const path = require('path'); +const uuidv4 = require('uuid/v4'); const myParser = require('body-parser'); -const jwt = require('jsonwebtoken'); -const jwtDecode = require('jwt-decode'); +const urls = require('./config/urls'); +const timeouts = require('./config/timeouts'); const version = require('./package.json').version; +const rp = require('request-promise'); const compression = require('compression'); const cache = require('./helpers/cache'); const formatDate = require('./helpers/formatDate.js'); @@ -24,16 +26,8 @@ const SERVE_HTML = (process.env.SERVE_HTML === 'true'); logger.info(`ENV: ${ENV}`); logger.info(`SERVE_HTML: ${SERVE_HTML}`); -// 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; -const SECRET = process.env.JWT_SECRET; - -const users = {}; // For the user sessions +const sessions = {}; // For the user sessions const startTime = formatDate(new Date()); -const TOKEN_EXPIRE = 60 * 60 * 24; const app = express(); @@ -53,7 +47,7 @@ if (ENV === 'local') { logger.info('Using Access-Control-Allow-Origin CORS headers'); app.use((req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); - res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); + res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization'); next(); }); } @@ -78,75 +72,68 @@ if (SERVE_HTML) { app.post('/login', (req, res) => { logger.info('Logging user in'); - // Get the username/password from the body of the POST + // Get the username from the body of the POST const username = req.body.username; - const password = req.body.password; - - if (ENV === 'local') { - /* - * For local environment, need to compare username/password against - * environment variables. If the provided username/password is correct, a - * new key:value pair is added to the 'users' variable. - * - * key:value - * username:hashed/salted(role,apiKey) - * - */ - if ((username === ADMIN_USERNAME && password === ADMIN_PASSWORD) - || (username === USER_USERNAME && password === USER_PASSWORD)) { - const apiKey = 'API Key'; - - let role = 'user'; - if (username === ADMIN_USERNAME) { - role = 'admin'; - } - - const payload = { username, role, apiKey }; - const jToken = jwt.sign(payload, SECRET, { - expiresIn: TOKEN_EXPIRE - }); - - // Add user to key:value json store - users[jToken] = { username, role }; - - logger.info('Successful login to local environment'); - res.setHeader('Content-Type', 'application/json'); - res.send(JSON.stringify({ jToken, username, role })); - } else { - logger.info('Unsuccessful login to local environment'); - // Return 401 NOT AUTHORIZED if incorrect username/password - res.sendStatus(401); - } - } else if (ENV === 'deployed') { - /* - * For the deployed environment, the username/password is sent off to the - * gateway, which will return 200 OK for a correct username/password or - * 401 UNAUTHORIZED if they are incorrect. - * - * - * - */ + + const basicAuth = req.get('Authorization'); + let options = { + method: 'POST', + uri: urls.AUTH_URL, + timeout: timeouts.API_GW, + headers: { + 'Content-Type': 'application/json', + Authorization: `${basicAuth}` + }, + json: true, + body: { username } + }; + if (ENV === 'prod') { + options = { + method: 'POST', + uri: urls.AUTH_URL, + timeout: timeouts.API_GW, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + Authorization: `${basicAuth}` + }, + json: true, + body: { username } + }; } + + rp(options) + .then((gatewayJson) => { + // Create user session + const accessToken = uuidv4(); + sessions[accessToken] = { + key: gatewayJson.key, + role: gatewayJson.role, + username + }; + + logger.info('Successful login'); + res.setHeader('Content-Type', 'application/json'); + return res.send(JSON.stringify({ + username, + accessToken, + role: gatewayJson.role + })); + }) + .catch((err) => { + logger.error('Unable to login, timeout or server error'); + if (err.statusCode) return res.sendStatus(err.statusCode); + return res.sendStatus(504); // Timeout + }); }); app.post('/checkToken', (req, res) => { logger.info('Checking token'); - const token = req.body.token; - if (users[token] !== undefined) { - jwt.verify(token, SECRET, (err) => { - if (err) { - delete users[token]; - logger.info('Invalid token'); - res.sendStatus(401); - } else { - const decode = jwtDecode(token); - const username = decode.username; - const role = decode.role; - logger.info('Valid token'); - res.setHeader('Content-Type', 'application/json'); - res.send(JSON.stringify({ token, username, role })); - } - }); + const accessToken = req.body.accessToken; + + if (sessions[accessToken]) { + logger.info('Valid token'); + res.setHeader('Content-Type', 'application/json'); + res.send(JSON.stringify({ username: sessions[accessToken].username, accessToken })); } else { logger.info('Invalid token'); res.sendStatus(401); @@ -156,9 +143,76 @@ app.post('/checkToken', (req, res) => { app.post('/logout', (req, res) => { const token = req.body.token; // Remove user from storage - delete users[token]; + delete sessions[token]; logger.info('Logging user out'); res.sendStatus(200); }); +app.post('/api', (req, res) => { + // re route api requests with API key + const method = req.body.method; + const endpoint = req.body.endpoint; + const accessToken = req.get('Authorization'); + + if (sessions[accessToken]) { + const key = sessions[accessToken].key; + if (method === 'GET') { + getApiEndpoint(`${urls.API_GW}/bi/${endpoint}`, key) + .then((response) => { + logger.info('Returning GET response from API Gateway'); + return res.send(response); + }) + .catch((err) => { + logger.info('Error in API Gateway for GET request'); + return res.status(err.statusCode).send(err); + }); + } else if (method === 'POST') { + const postBody = req.body.postBody; + postApiEndpoint(`${urls.API_GW}/bi/${endpoint}`, postBody, key) + .then((response) => { + logger.info('Returning POST response from API Gateway'); + return res.send(response); + }) + .catch((err) => { + logger.info('Error in API Gateway for POST request'); + return res.status(err.statusCode).send(err); + }); + } + } else { + logger.info('Unable to use /api endpoint, not authenticated'); + return res.sendStatus(401); + } +}); + +function getApiEndpoint(url, apiKey) { + logger.debug(`GET API endpoint for url: ${url}`); + const options = { + method: 'GET', + headers: { + 'Authorization': apiKey + }, + uri: url, + timeout: timeouts.API_GET + }; + + return rp(options); +} + +function postApiEndpoint(url, postBody, apiKey) { + logger.debug(`POST API endpoint for url: ${url}`); + const options = { + method: 'POST', + uri: url, + timeout: timeouts.API_POST, + headers: { + 'Authorization': apiKey, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(postBody), // '{"updatedBy":"name","vars":{"ent_name":"name"}}', + json: false + }; + + return rp(options); +} + module.exports = app; diff --git a/server/config/timeouts.js b/server/config/timeouts.js new file mode 100644 index 0000000..c4d6e99 --- /dev/null +++ b/server/config/timeouts.js @@ -0,0 +1,7 @@ +const timeouts = { + API_GW: 5000, + API_POST: 10000, + API_GET: 10000, +}; + +module.exports = timeouts; diff --git a/server/config/urls.js b/server/config/urls.js new file mode 100644 index 0000000..d4c8874 --- /dev/null +++ b/server/config/urls.js @@ -0,0 +1,8 @@ +const urls = { + AUTH_URL: 'http://localhost:3002/auth', + API_GW: 'http://localhost:3002', + API_URL: 'http://localhost:9000', + API_VERSION: 'v1', +}; + +module.exports = urls; diff --git a/server/helpers/salt.js b/server/helpers/salt.js new file mode 100644 index 0000000..96689e2 --- /dev/null +++ b/server/helpers/salt.js @@ -0,0 +1,27 @@ +const btoa = require('btoa'); + +/** + * Generate 16 bytes salt for bcrypt by seed + * + * Should return the same salt for the same seed + * + * @param {string} seed The seed for salt + * @return {string} The resulted salt + */ +module.exports = function (seed) { + // Salt must be 16 bytes + const bytes = []; + for (let i = 0, l = seed.length; i < l; i += 1) { + bytes.push(seed.charCodeAt(i)); + } + while (bytes.length < 16) { + bytes.push(0); + } + + // Convert byte array to base64 string + const salt = btoa(String.fromCharCode.apply(String, bytes.slice(0, 16))); + // const salt = btoa(String(...bytes.slice(0, 16))); + + // Adding header for bcrypt. Fake 10 rounds + return `$2a$10$${salt}`; +}; diff --git a/server/index.js b/server/index.js index ec9e9d4..2118065 100644 --- a/server/index.js +++ b/server/index.js @@ -1,18 +1,50 @@ 'use strict'; -// Rule exceptions: /* eslint strict: "off" */ /* eslint no-console: "off" */ +const fork = require('child_process').fork; const app = require('./app'); const logger = require('./logger'); const PORT = process.env.PORT || 3001; +// On a local environment, we mock the API Gateway with the a node script on localhost:3002 +const child = (process.env.ENV === 'local') ? fork('./server/apiGateway') : null; + logger.level = 'debug'; logger.info('Started Winston logger & created log file'); app.maxSockets = 500; app.listen(PORT, () => { + console.log(`bi-ui-node-server listening on port ${PORT}!`); logger.info(`bi-ui-node-server listening on port ${PORT}!`); }); + +// Cleanup Code - for before the application exits +process.stdin.resume(); // so the program will not close instantly + +function exitHandler(options, err) { + if (options.cleanup) { + if (process.env.ENV === 'local') { + console.log('Killing child process (bi-ui-mock-api-gateway)...'); + logger.info('Killing child process (bi-ui-mock-api-gateway)...'); + child.kill('SIGINT'); + } + } + if (err) console.log(err.stack); + if (options.exit) process.exit(); +} + +// Do something when app is closing +process.on('exit', exitHandler.bind(null, { cleanup: true })); + +// Catches ctrl+c event +process.on('SIGINT', exitHandler.bind(null, { exit: true })); + +// Catches "kill pid" (for example: nodemon restart) +process.on('SIGUSR1', exitHandler.bind(null, { exit: true })); +process.on('SIGUSR2', exitHandler.bind(null, { exit: true })); + +// Catches uncaught exceptions +process.on('uncaughtException', exitHandler.bind(null, { exit: true })); diff --git a/server/package.json b/server/package.json index e1b6fc6..44f31a0 100644 --- a/server/package.json +++ b/server/package.json @@ -14,9 +14,11 @@ "memory-cache": "^0.2.0", "body-parser": "^1.17.2", "express": "^4.14.0", - "jsonwebtoken": "^7.1.9", - "jwt-decode": "^2.2.0", "morgan": "^1.7.0", + "uuid": "^3.1.0", + "bcryptjs": "^2.4.3", + "request": "^2.81.0", + "request-promise": "^4.2.2", "winston": "^2.4.0" }, "engines": { diff --git a/src/actions/LoginActions.js b/src/actions/LoginActions.js index 11dd04a..acd45c8 100644 --- a/src/actions/LoginActions.js +++ b/src/actions/LoginActions.js @@ -24,12 +24,11 @@ */ import { browserHistory } from 'react-router'; +import base64 from 'base-64'; import { SET_AUTH, USER_LOGOUT, SENDING_REQUEST, SET_ERROR_MESSAGE, SET_USER_DETAILS } from '../constants/LoginConstants'; -import { SET_MATCH_QUERY, SET_RANGE_QUERY } from '../constants/ApiConstants'; import * as errorMessages from '../constants/MessageConstants'; import auth from '../utils/auth'; import { getUiInfo, getApiInfo } from '../actions/InfoActions'; -import { setQuery } from '../actions/ApiActions'; /** * Logs an user in @@ -48,7 +47,8 @@ export function login(username, password) { return; } - auth.login(username, password, (success, data) => { + const basicAuth = base64.encode(`${username}:${password}`); + auth.login(username, basicAuth, (success, data) => { // When the request is finished, hide the loading indicator dispatch(sendingRequest(false)); dispatch(setAuthState(success)); @@ -57,8 +57,10 @@ export function login(username, password) { dispatch(setUserState({ username, role: data.role, - apiKey: data.apiKey, + accessToken: data.accessToken, })); + sessionStorage.setItem('accessToken', data.accessToken); + sessionStorage.setItem('username', username); dispatch(getUiInfo()); dispatch(getApiInfo()); // We setQuery to {} as a hacky solution to the issue below: @@ -85,7 +87,7 @@ export function login(username, password) { /** * Check the users token */ -export function checkAuth(token) { +export function checkAuth(username, token) { return (dispatch) => { auth.checkToken(token, (success, data) => { dispatch(setAuthState(success)); @@ -93,10 +95,6 @@ export function checkAuth(token) { sessionStorage.clear(); forwardTo('/'); } else if (success) { - // We setQuery to {} as a hacky solution to the issue below: - // https://github.com/ONSdigital/bi-ui/issues/3 - // dispatch(setQuery(SET_MATCH_QUERY, {})); - // dispatch(setQuery(SET_RANGE_QUERY, {})); if (window.location.pathname === '/') { forwardTo('/Home'); } @@ -104,8 +102,9 @@ export function checkAuth(token) { dispatch(getApiInfo()); dispatch(setUserState({ username: data.username, - role: data.role, + accessToken: data.newAccessToken, })); + sessionStorage.setItem('accessToken', data.newAccessToken); } }); }; @@ -117,8 +116,8 @@ export function checkAuth(token) { export function logout() { return (dispatch) => { dispatch(sendingRequest(true)); - auth.logout((success) => { - if (success === true) { + auth.logout(sessionStorage.accessToken, (success) => { + if (success) { dispatch(sendingRequest(false)); dispatch(setAuthState(false)); localStorage.clear(); diff --git a/src/config/api-urls.js b/src/config/api-urls.js index 0386634..baea42e 100644 --- a/src/config/api-urls.js +++ b/src/config/api-urls.js @@ -1,6 +1,6 @@ const apiUrls = { AUTH_URL: 'http://localhost:3001', - API_URL: 'http://localhost:9000', + REROUTE_URL: 'http://localhost:3001/api', SEARCH_ENDPOINT: 'search?query=', API_VERSION: 'v1', }; diff --git a/src/reducers/login.js b/src/reducers/login.js index 3526699..e2caee3 100644 --- a/src/reducers/login.js +++ b/src/reducers/login.js @@ -23,6 +23,7 @@ const initialState = { currentlySending: false, loggedIn: false, errorMessage: '', + accessToken: '', }; // Takes care of changing the application state @@ -33,6 +34,7 @@ function loginReducer(state = initialState, action) { ...state, username: action.newState.username, role: action.newState.role, + accessToken: action.newState.accessToken, }); case SET_AUTH: return assign({}, state, { diff --git a/src/routes.js b/src/routes.js index 8d8f18f..1527ec3 100644 --- a/src/routes.js +++ b/src/routes.js @@ -40,16 +40,16 @@ export const store = createStoreWithMiddleware( // if there the token gets checked with the node server for authentication // if no token is present, the user gets redirected back to the login. function checkAuthentication(nextState, replaceState) { - if (sessionStorage.token) { - store.dispatch(checkAuth(sessionStorage.token)); + if (sessionStorage.accessToken && sessionStorage.username) { + store.dispatch(checkAuth(sessionStorage.username, sessionStorage.accessToken)); } else { replaceState(null, '/'); } } function checkLogin() { - if (sessionStorage.token) { - store.dispatch(checkAuth(sessionStorage.token)); + if (sessionStorage.accessToken && sessionStorage.username) { + store.dispatch(checkAuth(sessionStorage.username, sessionStorage.accessToken)); } } diff --git a/src/utils/apiSearch.js b/src/utils/apiSearch.js index 2ff1f4a..096c7c0 100644 --- a/src/utils/apiSearch.js +++ b/src/utils/apiSearch.js @@ -2,7 +2,7 @@ import config from '../config/api-urls'; -const { API_URL, API_VERSION, SEARCH_ENDPOINT } = config; +const { REROUTE_URL, API_VERSION, SEARCH_ENDPOINT } = config; /** * API lib for searching business-index-api @@ -14,8 +14,18 @@ const apiSearch = { * @param {Function} callback Called with returned data. */ match(query: string, callback: (success: boolean, data: {}, response?: {}) => void) { - fetch(`${API_URL}/${API_VERSION}/${SEARCH_ENDPOINT}${query}`, { - method: 'GET', + // fetch(`${REROUTE_URL}/${API_VERSION}/${SEARCH_ENDPOINT}${query}`, { + // method: 'GET', + fetch(`${REROUTE_URL}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': sessionStorage.getItem('accessToken'), + }, + body: JSON.stringify({ + method: 'GET', + endpoint: `${API_VERSION}/${SEARCH_ENDPOINT}${query}`, + }), }).then((response) => { if (response.status === 200) { return response.json().then((json) => { @@ -34,8 +44,18 @@ const apiSearch = { * @param {Function} callback Called with returned data. */ range(query: string, callback: (success: boolean, data: {}, response?: {}) => void) { - fetch(`${API_URL}/${API_VERSION}/search?${query}`, { - method: 'GET', + // fetch(`${REROUTE_URL}/${API_VERSION}/search?${query}`, { + // method: 'GET', + fetch(`${REROUTE_URL}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': sessionStorage.getItem('accessToken'), + }, + body: JSON.stringify({ + method: 'GET', + endpoint: `${API_VERSION}/search?${query}`, + }), }).then((response) => { if (response.status === 200) { return response.json().then((json) => { @@ -54,8 +74,19 @@ const apiSearch = { * @param {Function} callback Called with returned data. */ ubrn(id: string, callback: (success: boolean, data: {}, response?: {}) => void) { - fetch(`${API_URL}/${API_VERSION}/business/${id}`, { - method: 'GET', + // fetch(`${REROUTE_URL}/${API_VERSION}/business/${id}`, { + // method: 'GET', + // }).then((response) => { + fetch(`${REROUTE_URL}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': sessionStorage.getItem('accessToken'), + }, + body: JSON.stringify({ + method: 'GET', + endpoint: `${API_VERSION}/business/${id}`, + }), }).then((response) => { if (response.status === 200) { return response.json().then((json) => { diff --git a/src/utils/auth.js b/src/utils/auth.js index 6bcb65e..d4f1231 100644 --- a/src/utils/auth.js +++ b/src/utils/auth.js @@ -1,6 +1,7 @@ // @flow import config from '../config/api-urls'; +import base64 from 'base-64'; const { AUTH_URL } = config; @@ -15,7 +16,7 @@ const auth = { * @param {string} password The password of the user * @param {Function} callback Called after a user was logged in on the remote server */ - login(username: string, password: string, callback: (success: boolean, data: {}) => void) { + login(username: string, basicAuth: string, callback: (success: boolean, data: {}) => void) { // Do not need to check if user is already logged in, this is done in // routes.js before this method is called @@ -24,17 +25,19 @@ const auth = { method: 'POST', headers: { 'Content-Type': 'application/json', + Authorization: `Basic ${base64.encode('admin:admin')}`, }, - body: JSON.stringify({ username, password }), + body: JSON.stringify({ username }), }).then((response) => { if (response.status === 200) { return response.json().then((json) => { - const token: string = json.jToken; + // const token: string = json.jToken; const loginName: string = json.username; - const role: string = json.role; - sessionStorage.setItem('token', token); + const accessToken: string = json.accessToken; + // const role: string = json.role; + // sessionStorage.setItem('token', token); // Send auth request to save token username pair - callback(true, { token, loginName, role }); + callback(true, { username: loginName, accessToken }); }); } return callback(false, { message: 'Unable to login.' }); @@ -43,21 +46,21 @@ const auth = { return callback(false, { message: 'Server error: request timed out.' }); }); }, - checkToken(token: string, callback: (success: boolean, data: ?{}) => void) { + checkToken(accessToken: string, callback: (success: boolean, data: ?{}) => void) { fetch(`${AUTH_URL}/checkToken`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ token }), + body: JSON.stringify({ accessToken }), }).then((response) => { if (response.status === 200) { return response.json().then((json) => { - const newToken: string = json.token; + const newAccessToken: string = json.accessToken; const username: string = json.username; - const role: string = json.role; + // const role: string = json.role; // Send auth request to save token username pair - callback(true, { newToken, username, role }); + callback(true, { username, newAccessToken }); }); } return callback(false); @@ -69,19 +72,18 @@ const auth = { /** * Logs the current user out */ - logout(callback: (success: boolean) => void) { - const token: string = sessionStorage.token; + logout(accessToken: string, callback: (success: boolean) => void) { + // const token: string = sessionStorage.token; fetch(`${AUTH_URL}/logout`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ token }), - }).then((response) => { - if (response.status === 200) { - sessionStorage.clear(); - callback(true); - } + body: JSON.stringify({ accessToken }), + }).then(() => { + // Whatever the response, log the user out. + sessionStorage.clear(); + callback(true); }); }, onChange() {},