Skip to content

Commit e952f4c

Browse files
Working branch (#4)
1 parent 2638c9d commit e952f4c

File tree

11 files changed

+481
-44
lines changed

11 files changed

+481
-44
lines changed

omod/pom.xml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,31 @@
5151
<groupId>javax.servlet</groupId>
5252
<artifactId>javax.servlet-api</artifactId>
5353
</dependency>
54+
<dependency>
55+
<groupId>org.openmrs.module</groupId>
56+
<artifactId>uiframework-api</artifactId>
57+
</dependency>
58+
<dependency>
59+
<groupId>org.openmrs.module</groupId>
60+
<artifactId>appui-omod</artifactId>
61+
<version>${appuiVersion}</version>
62+
<type>jar</type>
63+
<scope>provided</scope>
64+
<exclusions>
65+
<exclusion>
66+
<artifactId>appui-api</artifactId>
67+
<groupId>org.openmrs.module</groupId>
68+
</exclusion>
69+
</exclusions>
70+
</dependency>
71+
72+
<dependency>
73+
<groupId>org.openmrs.module</groupId>
74+
<artifactId>appui-api</artifactId>
75+
<classifier>tests</classifier>
76+
<version>${appuiVersion}</version>
77+
<scope>test</scope>
78+
</dependency>
5479
</dependencies>
5580

5681
<build>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public License,
3+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5+
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6+
*
7+
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8+
* graphic logo is a trademark of OpenMRS Inc.
9+
*/
10+
package org.openmrs.module.smartonfhir.page.controller;
11+
12+
import org.openmrs.module.appframework.domain.AppDescriptor;
13+
import org.openmrs.module.appui.UiSessionContext;
14+
import org.openmrs.module.coreapps.helper.BreadcrumbHelper;
15+
import org.openmrs.ui.framework.UiUtils;
16+
import org.openmrs.ui.framework.page.PageModel;
17+
import org.springframework.web.bind.annotation.RequestParam;
18+
19+
public class FindPatientPageController {
20+
21+
/**
22+
* This page is built to be shared across multiple apps. To use it, you must pass an "app" request
23+
* parameter, which must be the id of an existing app that is an instance of
24+
* coreapps.template.findPatient
25+
*
26+
* @param model
27+
* @param app
28+
* @param sessionContext
29+
*/
30+
public void get(PageModel model, @RequestParam("app") AppDescriptor app, @RequestParam("token") String token,
31+
UiSessionContext sessionContext, UiUtils ui) {
32+
System.out.println("in FindPatientPageController" + token);
33+
model.addAttribute("afterSelectedUrl", app.getConfig().get("afterSelectedUrl").getTextValue() + "&token=" + token);
34+
model.addAttribute("heading", app.getConfig().get("heading").getTextValue());
35+
model.addAttribute("label", app.getConfig().get("label").getTextValue());
36+
model.addAttribute("showLastViewedPatients", app.getConfig().get("showLastViewedPatients").getBooleanValue());
37+
if (app.getConfig().get("registrationAppLink") == null) {
38+
model.addAttribute("registrationAppLink", "");
39+
} else {
40+
model.addAttribute("registrationAppLink", app.getConfig().get("registrationAppLink").getTextValue());
41+
}
42+
BreadcrumbHelper.addBreadcrumbsIfDefinedInApp(app, model, ui);
43+
}
44+
45+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public License,
3+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5+
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6+
*
7+
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8+
* graphic logo is a trademark of OpenMRS Inc.
9+
*/
10+
package org.openmrs.module.smartonfhir.web.filter;
11+
12+
import javax.servlet.FilterChain;
13+
import javax.servlet.ServletException;
14+
import javax.servlet.http.HttpServletRequest;
15+
import javax.servlet.http.HttpServletResponse;
16+
17+
import java.io.IOException;
18+
19+
import org.springframework.web.filter.OncePerRequestFilter;
20+
21+
/*
22+
* Custom CORS filter
23+
* To use this declare filter mapping in config.xml
24+
*/
25+
public class CORSFilter extends OncePerRequestFilter {
26+
27+
@Override
28+
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
29+
throws ServletException, IOException {
30+
// CORS "pre-flight" request
31+
response.addHeader("Access-Control-Allow-Credentials", "true");
32+
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
33+
response.addHeader("Access-Control-Allow-Headers", "Authorization");
34+
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
35+
response.addHeader("Access-Control-Allow-Origin", "*");
36+
response.addHeader("Access-Control-Max-Age", "1");
37+
38+
filterChain.doFilter(request, response);
39+
}
40+
}

omod/src/main/java/org/openmrs/module/smartonfhir/web/filter/SmartAuthenticationFilter.java

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -74,47 +74,51 @@ public void init(FilterConfig filterConfig) {
7474
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
7575
if (req instanceof HttpServletRequest) {
7676
final HttpServletRequest httpRequest = (HttpServletRequest) req;
77-
if (httpRequest.getRequestedSessionId() != null) {
78-
Context.logout();
79-
}
80-
81-
String authorization = httpRequest.getHeader("Authorization");
82-
if (!Context.isAuthenticated() && (authorization == null || !authorization.startsWith("Basic"))) {
83-
// KeycloakOIDCFilter does the actual request handling
84-
super.doFilter(req, res, (rq, rs) -> {});
85-
86-
if (res.isCommitted()) {
87-
return;
77+
// if (false) {
78+
if (!(httpRequest.getRequestURI().contains("/.well-known")
79+
|| httpRequest.getRequestURI().contains("/metadata"))) {
80+
if (httpRequest.getRequestedSessionId() != null) {
81+
Context.logout();
8882
}
8983

90-
if (httpRequest.getAttribute(KeycloakAccount.class.getName()) != null) {
91-
OidcKeycloakAccount account = (OidcKeycloakAccount) httpRequest
92-
.getAttribute(KeycloakAccount.class.getName());
84+
String authorization = httpRequest.getHeader("Authorization");
85+
if (!Context.isAuthenticated() && (authorization == null || !authorization.startsWith("Basic"))) {
86+
// KeycloakOIDCFilter does the actual request handling
87+
super.doFilter(req, res, (rq, rs) -> {});
9388

94-
String userName = account.getKeycloakSecurityContext().getToken().getPreferredUsername();
95-
Authenticated authenticated;
96-
try {
97-
authenticated = Context.authenticate(new SmartTokenCredentials(userName));
98-
}
99-
catch (ContextAuthenticationException e) {
100-
HttpServletResponse httpResponse = (HttpServletResponse) res;
101-
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Not authenticated");
89+
if (res.isCommitted()) {
10290
return;
10391
}
10492

105-
log.debug("The user '{}' was successfully authenticated as OpenMRS user {}", userName,
106-
authenticated.getUser());
107-
108-
// attempt to remove access_token from the query string
109-
Matcher m = ACCESS_TOKEN.matcher(httpRequest.getRequestURI());
110-
if (m.matches()) {
111-
httpRequest.getRequestDispatcher(m.replaceFirst("")).forward(req, res);
93+
if (httpRequest.getAttribute(KeycloakAccount.class.getName()) != null) {
94+
OidcKeycloakAccount account = (OidcKeycloakAccount) httpRequest
95+
.getAttribute(KeycloakAccount.class.getName());
96+
97+
String userName = account.getKeycloakSecurityContext().getToken().getPreferredUsername();
98+
Authenticated authenticated;
99+
try {
100+
authenticated = Context.authenticate(new SmartTokenCredentials(userName));
101+
}
102+
catch (ContextAuthenticationException e) {
103+
HttpServletResponse httpResponse = (HttpServletResponse) res;
104+
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Not authenticated");
105+
return;
106+
}
107+
108+
log.debug("The user '{}' was successfully authenticated as OpenMRS user {}", userName,
109+
authenticated.getUser());
110+
111+
// attempt to remove access_token from the query string
112+
Matcher m = ACCESS_TOKEN.matcher(httpRequest.getRequestURI());
113+
if (m.matches()) {
114+
httpRequest.getRequestDispatcher(m.replaceFirst("")).forward(req, res);
115+
return;
116+
}
117+
} else {
118+
HttpServletResponse httpResponse = (HttpServletResponse) res;
119+
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Not authenticated");
112120
return;
113121
}
114-
} else {
115-
HttpServletResponse httpResponse = (HttpServletResponse) res;
116-
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Not authenticated");
117-
return;
118122
}
119123
}
120124
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public License,
3+
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
4+
* obtain one at http://mozilla.org/MPL/2.0/. OpenMRS is also distributed under
5+
* the terms of the Healthcare Disclaimer located at http://openmrs.org/license.
6+
*
7+
* Copyright (C) OpenMRS Inc. OpenMRS is a registered trademark and the OpenMRS
8+
* graphic logo is a trademark of OpenMRS Inc.
9+
*/
10+
package org.openmrs.module.smartonfhir.web.filter;
11+
12+
import javax.servlet.Filter;
13+
import javax.servlet.FilterChain;
14+
import javax.servlet.FilterConfig;
15+
import javax.servlet.ServletException;
16+
import javax.servlet.ServletRequest;
17+
import javax.servlet.ServletResponse;
18+
import javax.servlet.http.HttpServletRequest;
19+
import javax.servlet.http.HttpServletResponse;
20+
21+
import java.io.IOException;
22+
23+
import lombok.extern.slf4j.Slf4j;
24+
25+
@Slf4j
26+
public class SmartForwardingFilter implements Filter {
27+
28+
@Override
29+
public void init(FilterConfig filterConfig) {
30+
}
31+
32+
@Override
33+
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
34+
if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
35+
HttpServletRequest request = (HttpServletRequest) req;
36+
if (request.getRequestURI().contains("/.well-known") || request.getRequestURI().contains("/metadata")) {
37+
req.getRequestDispatcher("/ms/smartConfig").forward(req, res);
38+
return;
39+
}
40+
if (request.getRequestURI().contains("/smartPatientSelected")) {
41+
req.getRequestDispatcher("/ms/smartPatientSelected").forward(req, res);
42+
return;
43+
}
44+
}
45+
46+
chain.doFilter(req, res);
47+
}
48+
49+
@Override
50+
public void destroy() {
51+
52+
}
53+
}

omod/src/main/java/org/openmrs/module/smartonfhir/web/servlet/SmartConfigServlet.java

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
import javax.servlet.http.HttpServletResponse;
1515

1616
import java.io.IOException;
17+
import java.util.ArrayList;
18+
import java.util.HashMap;
19+
import java.util.List;
1720

1821
import org.codehaus.jackson.map.ObjectMapper;
1922
import org.openmrs.module.smartonfhir.web.SmartConformance;
@@ -26,8 +29,8 @@ public class SmartConfigServlet extends HttpServlet {
2629

2730
public SmartConfigServlet() {
2831
this.smartConformance = new SmartConformance();
29-
smartConformance.setAuthorizationEndpoint("https://ehr.example.com/auth/authorize");
30-
smartConformance.setTokenEndpoint("https://ehr.example.com/auth/token");
32+
smartConformance.setAuthorizationEndpoint("http://localhost:8180/auth/realms/openmrs/protocol/openid-connect/auth");
33+
smartConformance.setTokenEndpoint("http://localhost:8180/auth/realms/openmrs/protocol/openid-connect/token");
3134
smartConformance.setTokenEndpointAuthMethodsSupported(new String[] { "client_secret_basic" });
3235
smartConformance.setRegistrationEndpoint("https://ehr.example.com/auth/register");
3336
smartConformance.setScopesSupported(
@@ -36,14 +39,70 @@ public SmartConfigServlet() {
3639
smartConformance.setManagementEndpoint("https://ehr.example.com/user/manage");
3740
smartConformance.setIntrospectionEndpoint("https://ehr.example.com/user/introspect");
3841
smartConformance.setRevocationEndpoint("https://ehr.example.com/user/revoke");
39-
smartConformance.setCapabilities(new String[] { "launch-ehr", "client-public", "client-confidential-symmetric",
40-
"context-ehr-patient", "sso-openid-connect" });
42+
smartConformance.setCapabilities(new String[] { "launch-standalone", "launch-ehr", "client-public",
43+
"client-confidential-symmetric", "context-ehr-patient", "sso-openid-connect" });
4144
}
4245

4346
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
47+
String fhirUri = "http://localhost:8080/openmrs/ws/fhir2/R3";
48+
String authUri = "http://localhost:8180/auth/realms/openmrs/protocol/openid-connect/auth";
49+
String tokenUri = "http://localhost:8180/auth/realms/openmrs/protocol/openid-connect/token";
50+
51+
HashMap<String, Object> codingMap = new HashMap<>();
52+
codingMap.put("system", "http://hl7.org/fhir/restful-security-service");
53+
codingMap.put("code", "SMART-on-FHIR");
54+
55+
List<HashMap<String, Object>> codingList = new ArrayList<>();
56+
codingList.add(codingMap);
57+
58+
HashMap<String, Object> serviceMap = new HashMap<>();
59+
serviceMap.put("coding", codingList);
60+
serviceMap.put("text", "OAuth2 using SMART-on-FHIR profile (see http://docs.smarthealthit.org)");
61+
62+
List<HashMap<String, Object>> serviceList = new ArrayList<>();
63+
serviceList.add(serviceMap);
64+
65+
HashMap<String, Object> tokenMap = new HashMap<>();
66+
tokenMap.put("url", "token");
67+
tokenMap.put("valueUri", tokenUri);
68+
69+
HashMap<String, Object> authorizeMap = new HashMap<>();
70+
authorizeMap.put("url", "authorize");
71+
authorizeMap.put("valueUri", authUri);
72+
73+
HashMap<String, Object> fhirMap = new HashMap<>();
74+
fhirMap.put("url", "fhir");
75+
fhirMap.put("valueUri", fhirUri);
76+
77+
List<HashMap<String, Object>> innerExtentionList = new ArrayList<>();
78+
innerExtentionList.add(tokenMap);
79+
innerExtentionList.add(authorizeMap);
80+
innerExtentionList.add(fhirMap);
81+
82+
HashMap<String, Object> extentionMap = new HashMap<>();
83+
extentionMap.put("url", "http://fhir-registry.smarthealthit.org/StructureDefinition/oauth-uris");
84+
extentionMap.put("extension", innerExtentionList);
85+
86+
List<HashMap<String, Object>> extentionList = new ArrayList<>();
87+
extentionList.add(extentionMap);
88+
89+
HashMap<String, Object> securityMap = new HashMap<>();
90+
securityMap.put("service", serviceList);
91+
securityMap.put("extension", extentionList);
92+
93+
HashMap<String, Object> restMap = new HashMap<>();
94+
restMap.put("security", securityMap);
95+
96+
List<HashMap<String, Object>> restList = new ArrayList<>();
97+
restList.add(restMap);
98+
99+
HashMap<String, Object> metadataMap = new HashMap<>();
100+
metadataMap.put("resourceType", "Conformance");
101+
metadataMap.put("rest", restList);
102+
44103
res.setContentType("application/json");
45104
res.setCharacterEncoding("UTF-8");
46105
res.setStatus(200);
47-
objectMapper.writeValue(res.getWriter(), smartConformance);
106+
objectMapper.writeValue(res.getWriter(), metadataMap);
48107
}
49108
}

0 commit comments

Comments
 (0)