Skip to content

Commit

Permalink
registers/auth, sends encrypted FHIR messages, needs cleanup.
Browse files Browse the repository at this point in the history
  • Loading branch information
jcschaff committed Jan 8, 2018
1 parent 6cac3ac commit d07cf14
Show file tree
Hide file tree
Showing 17 changed files with 1,251 additions and 28 deletions.
26 changes: 25 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,14 @@
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.10</version>
</dependency>

<!-- <dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
<version>${hapi.fhir.version}</version>
Expand All @@ -62,6 +68,19 @@
<artifactId>hapi-fhir-validation-resources-dstu2</artifactId>
<version>${hapi.fhir.version}</version>
</dependency>
-->
<!-- This dependency includes the core HAPI-FHIR classes -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-base</artifactId>
<version>1.3</version>
</dependency>
<!-- At least one "structures" JAR must also be included -->
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-structures-dstu2</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>com.phloc</groupId>
<artifactId>phloc-schematron</artifactId>
Expand All @@ -72,6 +91,11 @@
<artifactId>phloc-commons</artifactId>
<version>4.4.11</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.9.33</version>
</dependency>
</dependencies>

</project>
16 changes: 5 additions & 11 deletions src/main/java/edu/uconn/c3pro/mockmobile/C3proApiDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,10 @@
import com.github.scribejava.core.builder.api.DefaultApi20;

public class C3proApiDefinition extends DefaultApi20 {
private final String baseurl_auth;

protected C3proApiDefinition() {
}

private static class InstanceHolder {
private static final C3proApiDefinition INSTANCE = new C3proApiDefinition();
}

public static C3proApiDefinition instance() {
return InstanceHolder.INSTANCE;
protected C3proApiDefinition(String baseurl_auth) {
this.baseurl_auth = baseurl_auth;
}

@Override
Expand All @@ -23,12 +17,12 @@ public ClientAuthenticationType getClientAuthenticationType() {

@Override
public String getAccessTokenEndpoint() {
return "http://localhost:8081/c3pro/auth";
return baseurl_auth+"/c3pro/auth";
}

@Override
protected String getAuthorizationBaseUrl() {
return "http://localhost:8082/oauth/authorize";
return baseurl_auth+"/c3pro/register";
}


Expand Down
125 changes: 112 additions & 13 deletions src/main/java/edu/uconn/c3pro/mockmobile/Client.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,44 @@
package edu.uconn.c3pro.mockmobile;

import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import javax.net.ssl.TrustManagerFactory;

import org.asynchttpclient.DefaultAsyncHttpClientConfig;
import org.asynchttpclient.filter.FilterContext;
import org.asynchttpclient.filter.FilterException;
import org.asynchttpclient.filter.RequestFilter;
//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.asynchttpclient.netty.ssl.DefaultSslEngineFactory;
import org.bch.c3pro.server.exception.C3PROException;
import org.bch.c3pro.server.external.Queue;
import org.bch.c3pro.server.iresource.ConsentResourceProvider;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.model.OAuth2AccessToken;
import com.github.scribejava.core.model.OAuthRequest;
import com.github.scribejava.core.model.Response;
import com.github.scribejava.core.model.Verb;
import com.github.scribejava.core.oauth.OAuth20Service;
import com.github.scribejava.httpclient.ahc.AhcHttpClient;
import com.github.scribejava.httpclient.ahc.AhcHttpClientConfig;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import ca.uhn.fhir.model.dstu2.resource.Contract;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;

public class Client {

Expand All @@ -38,10 +58,22 @@ public <T> FilterContext<T> filter(FilterContext<T> arg0) throws FilterException
// must match antispam token in auth/resource database
// (check debug log of auth server for token to add to database)
//
String antispam = "myantispam";
String baseurl_auth = "https://api.jcschaff.net:8888";
//String baseurl_auth = "https://2amoveu7z2.execute-api.us-east-1.amazonaws.com/alpha";
//String baseurl_auth = "https://api.jcschaff.net/c3pro/alpha";
String baseurl_api = "https://api.jcschaff.net:8889";
//String baseurl_auth = "https://2amoveu7z2.execute-api.us-east-1.amazonaws.com/alpha";
//String baseurl_auth = "https://api.jcschaff.net/c3pro/alpha";

String antispam = "myantispam";
TrustManagerFactory trustManagerFactory = InsecureTrustManagerFactory.INSTANCE;
SslContextBuilder insecureSslBuilder = SslContextBuilder.forClient().trustManager(trustManagerFactory);
SslContext sslContext = insecureSslBuilder.build();

final AhcHttpClientConfig registrationClientConfig = new AhcHttpClientConfig(new DefaultAsyncHttpClientConfig.Builder()
.setMaxConnections(5)
.setSslContext(sslContext)
.setSslEngineFactory(new DefaultSslEngineFactory())
.setRequestTimeout(10000)
.setPooledConnectionIdleTimeout(1000)
.addRequestFilter(requestFilter)
Expand All @@ -61,10 +93,12 @@ public <T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException
put("Content-Type", "application/json");
put("Accept","application/json");
}};
Registration registration = new Registration(true,"your apple-supplied app purchase receipt");
String registrationJSON = gson.toJson(registration);
Registration registration = new Registration(true,"NO-APP-RECEIPT");
ObjectMapper objectMapper = new ObjectMapper();
String registrationJSON = objectMapper.writeValueAsString(registration);
//String registrationJSON = gson.toJson(registration);
byte[] bodyContents = registrationJSON.getBytes("UTF-8");
final String REGISTRATION_URL = "http://localhost:8081/c3pro/register";
final String REGISTRATION_URL = baseurl_auth+"/c3pro/register";

Response response = null;
try (AhcHttpClient client = new AhcHttpClient(registrationClientConfig);){
Expand All @@ -74,6 +108,10 @@ public <T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException
}

String registrationResponseJSON = response.getBody();
if ( HttpResponseStatus.valueOf(response.getCode()) != HttpResponseStatus.CREATED) {
System.err.println(toPrettyFormat(response.getBody()));
throw new RuntimeException("return code '"+HttpResponseStatus.valueOf(response.getCode())+"', unexpected during registration");
}
RegistrationResponse registrationResponse = gson.fromJson(registrationResponseJSON, RegistrationResponse.class);
System.out.println("registration gotten back from server: "+gson.toJson(registrationResponse));

Expand All @@ -91,6 +129,8 @@ public <T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException

final AhcHttpClientConfig authorizationClientConfig = new AhcHttpClientConfig(new DefaultAsyncHttpClientConfig.Builder()
.setMaxConnections(5)
.setSslContext(sslContext)
.setSslEngineFactory(new DefaultSslEngineFactory())
.setRequestTimeout(10000)
.setPooledConnectionIdleTimeout(1000)
.addRequestFilter(requestFilter)
Expand All @@ -113,7 +153,7 @@ public <T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException
.debug()
.debugStream(debugStream)
.httpClientConfig(authorizationClientConfig)
.build(C3proApiDefinition.instance());){
.build(new C3proApiDefinition(baseurl_auth));){

System.out.println("before service.getAccessTokenClientCredentialsGrant()");
OAuth2AccessToken accessToken = service.getAccessTokenClientCredentialsGrant();
Expand All @@ -126,14 +166,19 @@ public <T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException
//
// next, we'll exercise the resource server using the same "service".
//

// FhirContext ctx = FhirContext.forDstu2Hl7Org();
ConsentResourceProvider consentProvider = new ConsentResourceProvider(
new PostQueue(baseurl_api+"/c3pro/fhirenc/Contract",service,accessToken)
);
Contract contract = new Contract();
consentProvider.createContract(contract);

//
// retrieve questionnaire "q1"
//
{
// FhirContext ctx = FhirContext.forDstu2(); // Dstu2Hl7Org();
// IParser fhirParser = ctx.newJsonParser();
//
// //
// // retrieve questionnaire "q1"
// //
// final OAuthRequest request = new OAuthRequest(Verb.GET, "https://localhost:8082/c3pro/fhir/Questionnaire/q1");
// final OAuthRequest request = new OAuthRequest(Verb.GET, baseurl_api+"/c3pro/fhir/Questionnaire/q1");
// service.signRequest(accessToken, request);
// final Response questionnaireResponse = service.execute(request);
// if (questionnaireResponse.getCode() != 200) {
Expand All @@ -142,10 +187,64 @@ public <T> FilterContext<T> filter(FilterContext<T> ctx) throws FilterException
// final String questionnaireString = response.getBody();
// final Questionnaire questionnaire = fhirParser.parseResource(Questionnaire.class, questionnaireString);
// System.out.println("received questionnaire: "+fhirParser.encodeResourceToString(questionnaire));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}

public static class PostQueue implements Queue {
final String url;
final OAuth20Service service;
final OAuth2AccessToken accessToken;


public PostQueue(String url, OAuth20Service service, OAuth2AccessToken accessToken) {
this.url = url;
this.service = service;
this.accessToken = accessToken;
}

@Override
public void sendMessageEncrypted(String resource, PublicKey key, String UUIDKey, String version)
throws C3PROException {
try {
MessageEncryptionService encryptionService = new MessageEncryptionService();
EncryptedMessage encryptedConsentMessage = encryptionService.encryptMessage(resource, key, UUIDKey, version);
postEncrypted(service, accessToken, encryptedConsentMessage, url);
} catch (InterruptedException | ExecutionException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

private static void postEncrypted(OAuth20Service service, OAuth2AccessToken accessToken,
EncryptedMessage encryptedConsentMessage, String url)
throws JsonProcessingException, InterruptedException, ExecutionException, IOException {

final OAuthRequest request = new OAuthRequest(Verb.POST, url);
String encryptedConsentMessageJSON = new ObjectMapper().writeValueAsString(encryptedConsentMessage);
request.setPayload(encryptedConsentMessageJSON);
request.addHeader("Content-Type", "application/json");
request.addHeader("Accept","application/json");
service.signRequest(accessToken, request);
final Response consentResponse = service.execute(request);
if (consentResponse.getCode() != 200) {
throw new RuntimeException("unexpected return code "+consentResponse.getCode()+" - "+consentResponse.getMessage());
}
}

public static String toPrettyFormat(String jsonString)
{
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(jsonString).getAsJsonObject();

Gson gson = new GsonBuilder().setPrettyPrinting().create();
String prettyJson = gson.toJson(json);

return prettyJson;
}
}
62 changes: 62 additions & 0 deletions src/main/java/edu/uconn/c3pro/mockmobile/EncryptedMessage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package edu.uconn.c3pro.mockmobile;

/**
* HTTP/1.1 POST /c3pro/fhirenc/*
* {
* "message":{{The encrypted fhir resource}},
* "symmetric_key": {{The encrypted AES symmetric key used to encrypt the message}},
* "key_id": {{The rsa key id used to encrypt the symmetric key}},
* "version": {{0.9.0 or 1.0.2}}
* }
*
**/

public class EncryptedMessage {
private String message;
private String symmetric_key;
private String key_id;
private String version;

public EncryptedMessage() {
}

public EncryptedMessage(String message, String symmetric_key, String key_id, String version) {
this.message = message;
this.symmetric_key = symmetric_key;
this.key_id = key_id;
this.version = version;
}

public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}

public String getSymmetric_key() {
return symmetric_key;
}

public void setSymmetric_key(String symmetric_key) {
this.symmetric_key = symmetric_key;
}

public String getKey_id() {
return key_id;
}

public void setKey_id(String key_id) {
this.key_id = key_id;
}

public String getVersion() {
return version;
}

public void setVersion(String version) {
this.version = version;
}

}
Loading

0 comments on commit d07cf14

Please sign in to comment.