Skip to content
This repository has been archived by the owner on Apr 8, 2024. It is now read-only.

Commit

Permalink
Merge branch 'release/v1.1.0-RC3'
Browse files Browse the repository at this point in the history
  • Loading branch information
subigre committed Apr 22, 2021
2 parents 9818cdd + 36aa4bd commit ec389ee
Show file tree
Hide file tree
Showing 16 changed files with 442 additions and 68 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ The implementation is based on [Apache Camel](https://camel.apache.org/) and [Op

## Releases

##### 2021, April 22
v1.1.0-RC3 - Add support for Basic and OAuth 2.0 Authentication.

##### 2021, April 21
v1.1.0-RC2 - Release Candidate 2

##### 2021, April 13
v1.1.0-RC1 - Release candidate that includes major refactoring of the Conversion API and adds support for new FHIR resources and profiles.

Expand Down
27 changes: 13 additions & 14 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<groupId>org.ehrbase.fhirbridge</groupId>
<artifactId>fhir-bridge</artifactId>
<version>1.1.0-RC2</version>
<version>1.1.0-RC3</version>

<name>FHIR Bridge</name>

Expand Down Expand Up @@ -214,16 +214,6 @@
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.javers</groupId>
<artifactId>javers-core</artifactId>
<version>5.14.0</version>
</dependency>
<dependency>
<groupId>io.github.classgraph</groupId>
<artifactId>classgraph</artifactId>
<version>4.8.97</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
Expand All @@ -236,6 +226,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
Expand Down Expand Up @@ -295,9 +289,14 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.2</version>
<groupId>org.javers</groupId>
<artifactId>javers-core</artifactId>
<version>5.14.0</version>
</dependency>
<dependency>
<groupId>io.github.classgraph</groupId>
<artifactId>classgraph</artifactId>
<version>4.8.97</version>
</dependency>
</dependencies>

Expand Down
34 changes: 34 additions & 0 deletions src/main/java/org/ehrbase/fhirbridge/config/CorsConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.ehrbase.fhirbridge.config;

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
* {@link Configuration} for CORS.
*
* @since 1.1.0
*/
@Configuration
@EnableConfigurationProperties(CorsProperties.class)
public class CorsConfiguration {

@Bean
public FilterRegistrationBean<CorsFilter> cors(CorsProperties properties) {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
org.springframework.web.cors.CorsConfiguration config = new org.springframework.web.cors.CorsConfiguration();
config.setAllowCredentials(properties.isAllowCredentials());
config.setAllowedHeaders(properties.getAllowedHeaders());
config.setAllowedMethods(properties.getAllowedMethods());
config.setAllowedOrigins(properties.getAllowedOrigins());
source.registerCorsConfiguration("/**", config);

FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE); //this is what ensures CORS setting overrides all else
return bean;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,53 @@

import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.List;

/**
* {@link ConfigurationProperties ConfigurationProperties} to configure HAPI FHIR.
* {@link ConfigurationProperties ConfigurationProperties} to configure CORS.
*
* @since 1.0.0
*/
@ConfigurationProperties(prefix = "fhir-bridge.fhir.cors")
public class FhirCorsProperties {
@ConfigurationProperties(prefix = "fhir-bridge.cors")
public class CorsProperties {

private boolean allowCredentials = false;

private List<String> allowedHeaders;

private String allowedHeaders;
private List<String> allowedMethods;

private String allowedMethods;
private List<String> allowedOrigins;

private String allowedOrigins;
public boolean isAllowCredentials() {
return allowCredentials;
}

public void setAllowCredentials(boolean allowCredentials) {
this.allowCredentials = allowCredentials;
}

public String getAllowedHeaders() {
public List<String> getAllowedHeaders() {
return allowedHeaders;
}

public void setAllowedHeaders(String allowedHeaders) {
public void setAllowedHeaders(List<String> allowedHeaders) {
this.allowedHeaders = allowedHeaders;
}

public String getAllowedMethods() {
public List<String> getAllowedMethods() {
return allowedMethods;
}

public void setAllowedMethods(String allowedMethods) {
public void setAllowedMethods(List<String> allowedMethods) {
this.allowedMethods = allowedMethods;
}

public String getAllowedOrigins() {
public List<String> getAllowedOrigins() {
return allowedOrigins;
}

public void setAllowedOrigins(String allowedOrigins) {
public void setAllowedOrigins(List<String> allowedOrigins) {
this.allowedOrigins = allowedOrigins;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import org.apache.http.impl.client.HttpClientBuilder;
import org.ehrbase.client.openehrclient.OpenEhrClientConfig;
import org.ehrbase.client.openehrclient.defaultrestclient.DefaultRestClient;
import org.ehrbase.fhirbridge.config.ehrbase.AuthorizationType;
import org.ehrbase.fhirbridge.ehr.ResourceTemplateProvider;
import org.ehrbase.webtemplate.templateprovider.TemplateProvider;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
Expand All @@ -20,7 +19,7 @@
import java.net.URISyntaxException;

/**
* {@link Configuration Configuration} for EHRbase SDK.
* {@link Configuration} for EHRbase SDK.
*/
@Configuration
@EnableConfigurationProperties(EhrbaseProperties.class)
Expand Down Expand Up @@ -52,7 +51,7 @@ private HttpClient httpClient() {
HttpClientBuilder builder = HttpClientBuilder.create();

EhrbaseProperties.Security security = properties.getSecurity();
if (security.getType() == AuthorizationType.BASIC_AUTH) {
if (security.getType() == EhrbaseProperties.AuthorizationType.BASIC_AUTH) {
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(security.getUsername(), security.getPassword()));
builder.setDefaultCredentialsProvider(credentialsProvider);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.ehrbase.fhirbridge.config;

import org.ehrbase.fhirbridge.config.ehrbase.AuthorizationType;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
Expand Down Expand Up @@ -76,4 +75,9 @@ public void setPrefix(String prefix) {
this.prefix = prefix;
}
}

public enum AuthorizationType {

BASIC_AUTH, NONE
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import ca.uhn.fhir.rest.server.IPagingProvider;
import ca.uhn.fhir.rest.server.IServerAddressStrategy;
import ca.uhn.fhir.rest.server.IServerConformanceProvider;
import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor;
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
import org.ehrbase.fhirbridge.security.SmartOnFhirAuthorizationInterceptor;
import org.hl7.fhir.r4.model.CapabilityStatement;
import org.openehealth.ipf.boot.fhir.IpfBootFhirServlet;
import org.openehealth.ipf.boot.fhir.IpfFhirConfigurationProperties;
Expand All @@ -15,13 +15,12 @@
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;

/**
* {@link Configuration Configuration} for IPF FHIR Servlet.
*/
@Configuration
@EnableConfigurationProperties(FhirCorsProperties.class)
@EnableConfigurationProperties(CorsProperties.class)
public class IpfFhirConfiguration {

@Bean
Expand All @@ -33,8 +32,7 @@ public IpfFhirServlet fhirServlet(IpfFhirConfigurationProperties properties,
IServerAddressStrategy serverAddressStrategy,
INarrativeGenerator narrativeGenerator,
RequestValidatingInterceptor requestValidatingInterceptor,
CorsInterceptor corsInterceptor) {

ObjectProvider<SmartOnFhirAuthorizationInterceptor> authorizationInterceptors) {
IpfFhirServlet fhirServlet = new IpfBootFhirServlet(fhirContext, pagingProvider);
IpfFhirConfigurationProperties.Servlet servletProperties = properties.getServlet();
fhirServlet.setLogging(servletProperties.isLogging());
Expand All @@ -52,19 +50,7 @@ public IpfFhirServlet fhirServlet(IpfFhirConfigurationProperties properties,

// Register interceptors
fhirServlet.registerInterceptor(requestValidatingInterceptor);
fhirServlet.registerInterceptor(corsInterceptor);

authorizationInterceptors.ifAvailable(fhirServlet::registerInterceptor);
return fhirServlet;
}

@Bean
public CorsInterceptor corsInterceptor(FhirCorsProperties properties) {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedHeader(properties.getAllowedHeaders());
configuration.addAllowedOrigin(properties.getAllowedOrigins());
configuration.addAllowedMethod(properties.getAllowedMethods());
CorsInterceptor interceptor = new CorsInterceptor(configuration);
interceptor.setConfig(configuration);
return interceptor;
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package org.ehrbase.fhirbridge.config;

import org.ehrbase.fhirbridge.security.SmartOnFhirAuthorizationInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.web.SecurityFilterChain;

/**
* {@link Configuration Configuration} for security.
Expand Down Expand Up @@ -68,11 +75,32 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
@Configuration(proxyBeanMethods = false)
@EnableWebSecurity
@ConditionalOnProperty(value = "fhir-bridge.security.authentication-type", havingValue = "oauth2")
protected static class Oauth2AuthenticationConfiguration extends WebSecurityConfigurerAdapter {
protected static class Oauth2AuthenticationConfiguration {

// TODO: Add OAuth 2.0 configuration
public Oauth2AuthenticationConfiguration() {
throw new UnsupportedOperationException("Not yet implemented");
private final SecurityProperties properties;

public Oauth2AuthenticationConfiguration(SecurityProperties properties) {
this.properties = properties;
}

@Bean
public JwtDecoder jwtDecoder() {
return NimbusJwtDecoder
.withJwkSetUri(properties.getOauth2().getJwkSetUri())
.jwsAlgorithm(SignatureAlgorithm.from(properties.getOauth2().getJwsAlgorithm()))
.build();
}

@Bean
public SecurityFilterChain jwtSecurityFilterChain(HttpSecurity http) throws Exception {
http.authorizeRequests(requests -> requests.anyRequest().authenticated());
http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}

@Bean
public SmartOnFhirAuthorizationInterceptor authorizationInterceptor() {
return new SmartOnFhirAuthorizationInterceptor();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class SecurityProperties {

private final Basic basic = new Basic();

private final OAuth2 oauth2 = new OAuth2();

public AuthenticationType getAuthenticationType() {
return authenticationType;
}
Expand All @@ -24,6 +26,10 @@ public Basic getBasic() {
return basic;
}

public OAuth2 getOauth2() {
return oauth2;
}

public enum AuthenticationType {

/**
Expand Down Expand Up @@ -64,4 +70,33 @@ public void setPassword(String password) {
this.password = password;
}
}

public static class OAuth2 {

/**
* JSON Web Key URI to use to verify the JWT token.
*/
private String jwkSetUri;

/**
* JSON Web Algorithm used for verifying the digital signatures.
*/
private String jwsAlgorithm = "RS256";

public String getJwkSetUri() {
return jwkSetUri;
}

public void setJwkSetUri(String jwkSetUri) {
this.jwkSetUri = jwkSetUri;
}

public String getJwsAlgorithm() {
return jwsAlgorithm;
}

public void setJwsAlgorithm(String jwsAlgorithm) {
this.jwsAlgorithm = jwsAlgorithm;
}
}
}

This file was deleted.

Loading

0 comments on commit ec389ee

Please sign in to comment.