From 7b792458d045b7f0a100f1d56b0e55485d494a75 Mon Sep 17 00:00:00 2001 From: Paul McBride Date: Tue, 1 Mar 2022 12:30:33 +0000 Subject: [PATCH] Security Option II changes Signed-off-by: Paul McBride --- .DS_Store | Bin 0 -> 6148 bytes build/.DS_Store | Bin 6148 -> 6148 bytes build/config/default.json5 | 1 + build/config/keycloak.json | 8 +++ package.json | 1 + src/index.js | 109 ++++++++++++++++++++++++++++++------- src/lib/PatientSearch.js | 45 ++++++++++----- 7 files changed, 129 insertions(+), 35 deletions(-) create mode 100644 .DS_Store create mode 100644 build/config/keycloak.json diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..16d875f048b003f89438f610b00ecfc05d69253a GIT binary patch literal 6148 zcmeH~J&pn~427Thk&tL8DbsL(y+MTF1YBUnPJ=WO#fm;h=h<(?J6KYLuU74ZjM<6h0 J5P^Rs@C1L66M6su literal 0 HcmV?d00001 diff --git a/build/.DS_Store b/build/.DS_Store index 978b171fb27c6ac4781ae9b7a012a5b0b57764bf..355d26711fa6b53f6aeb7324406e72cc891a4e22 100644 GIT binary patch delta 166 zcmZoMXffEJ&ZM+6sURn_xWvHV8Y2@k3o9Et2RjEhM{ICLetB?7Vo7PS)8ud_?=(&h z&UgXI>S`ln6CDL(WAj=ag=#}%a|;~>OH;GjT22m8Wqs?Q`0SkAy!>tkFkoba&YsGdss$egK_IC2arz delta 160 zcmZoMXffEJ&SY>hsURn_xWvHVIwKP^3o9Et2L~4y7cW6A-A%s qx~8^nCIc8SGD2tuekcv2W=;OZB+tskki}5EnTz=o%Vu_tzx)99@g-CM diff --git a/build/config/default.json5 b/build/config/default.json5 index 21fc0bf..bd433c0 100644 --- a/build/config/default.json5 +++ b/build/config/default.json5 @@ -2480,6 +2480,7 @@ }, }, patientsPerPage: 25, + authEnabled: false, timeout: 20000, renderSelectedOnly: false, fhirViewer: { diff --git a/build/config/keycloak.json b/build/config/keycloak.json new file mode 100644 index 0000000..0919ae0 --- /dev/null +++ b/build/config/keycloak.json @@ -0,0 +1,8 @@ +{ + "realm": "test", + "auth-server-url": "https://localhost:8443/auth", + "ssl-required": "external", + "resource": "inferno", + "public-client": true, + "confidential-port": 0 +} diff --git a/package.json b/package.json index d6f72e7..5f3a27e 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "if-env": "^1.0.0", "jquery": "^3.2.1", "json5": "^0.5.1", + "keycloak-js": "^17.0.0", "less": "^2.7.2", "less-loader": "^4.0.3", "mixin-deep": "^1.2.0", diff --git a/src/index.js b/src/index.js index 4d410b4..e9f049f 100644 --- a/src/index.js +++ b/src/index.js @@ -8,27 +8,96 @@ import PatientList from "./components/PatientList"; import { Router, Route, Switch } from "react-router"; import createHistory from "history/createHashHistory"; import jQuery from "jquery"; +import Keycloak from "keycloak-js"; +import JSON5 from "json5"; +import { parseQueryString } from "./lib"; window.$ = window.jQuery = jQuery; -const history = createHistory(); - -ReactDOM.render( - - - - - - - - - - , - document.getElementById("main") -); - -$(function () { - $("body").tooltip({ - selector: ".patient-detail-page [title]", - }); +let authEnabled = false; +const DEFAULT_CONFIG = "default"; +let { config, ...params } = parseQueryString(window.location.search); + +jQuery.ajax({ + url: `./config/${config || DEFAULT_CONFIG}.json5`, + dataType: "text", + cache: false, + async: false, + success: (json) => { + json = JSON5.parse(json); + authEnabled = json.authEnabled; + }, }); + +if (authEnabled) { + let keycloak = new Keycloak("config/keycloak.json"); + + keycloak.onTokenExpired = function () { + keycloak.updateToken().then((refreshed) => { + if (refreshed) { + sessionStorage.setItem("access-token", keycloak.token); + } + }); + }; + + keycloak + .init({ + onLoad: "login-required", + + scope: "patient/*.read", + }) + .then(function (authenticated) { + if (authenticated) { + sessionStorage.setItem("access-token", keycloak.token); + + const history = createHistory(); + + ReactDOM.render( + + + + + + + + + + , + document.getElementById("main") + ); + + $(function () { + $("body").tooltip({ + selector: ".patient-detail-page [title]", + }); + }); + } + }) + .catch(function () { + alert( + "Failed to initialize KeyCloak adapter. Check KeyCloak config file." + ); + }); +} else { + const history = createHistory(); + + ReactDOM.render( + + + + + + + + + + , + document.getElementById("main") + ); + + $(function () { + $("body").tooltip({ + selector: ".patient-detail-page [title]", + }); + }); +} diff --git a/src/lib/PatientSearch.js b/src/lib/PatientSearch.js index 958ea28..631bebe 100644 --- a/src/lib/PatientSearch.js +++ b/src/lib/PatientSearch.js @@ -526,12 +526,12 @@ export default class PatientSearch { .forEach((token) => { if (token.indexOf("-") === 0) { params.push({ - name: "_sort", - value: token, + name: "_sort:desc", + value: token.substring(1), }); } else { params.push({ - name: "_sort", + name: "_sort:asc", value: token, }); } @@ -836,18 +836,33 @@ export default class PatientSearch { if (server.type == "DSTU-2") { data = data.replace(/\bdeceased=(true|false)\b/gi, ""); } - - // prepare the base options for the patient ajax request - let options = { - url: `${server.url}/Patient/_search`, - method: "POST", - processData: false, - data, - headers: { - accept: "application/fhir+json", - "content-type": "application/x-www-form-urlencoded", - }, - }; + // Take Access token from session storage if its available ie. if KeyCloak enabled authentication enabled. + // And only include authorization header if access token is available + let keycloakToken = sessionStorage.getItem("access-token"); + + let options = keycloakToken + ? { + url: `${server.url}/Patient/_search`, + method: "POST", + processData: false, + data, + headers: { + accept: "application/fhir+json", + "content-type": "application/x-www-form-urlencoded", + + authorization: "Bearer " + keycloakToken, + }, + } + : { + url: `${server.url}/Patient/_search`, + method: "POST", + processData: false, + data, + headers: { + accept: "application/fhir+json", + "content-type": "application/x-www-form-urlencoded", + }, + }; return this.getPatientIDs(server) .then((ids) => {