Skip to content

Commit

Permalink
Merge pull request #1 from opensrp/keycloak-integration
Browse files Browse the repository at this point in the history
Provide authentication support via Keycloak
  • Loading branch information
rehammuzzamil authored Jun 17, 2021
2 parents cb89bce + a81a75f commit a4b86ba
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 0 deletions.
16 changes: 16 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Default ignored files
/shelf/
/workspace.xml
target/
.project
.classpath
.settings/
.DS_Store
.idea/
*.iml
*.ipr
*.iws
logfile
*.log*
.springBeans
.gradle/
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Opensrp Server FHIR Security Auth

This repository provides spring security authentication configuration through Keycloak authorisation servers.
90 changes: 90 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.smartregister</groupId>

<artifactId>hapi-fhir-opensrp-security-config</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>opensrp-server-fhir-security-auth</name>
<description>FHIR Security Authentication module</description>
<url>https://github.com/opensrp/opensrp-server-fhir-security-auth</url>

<properties>
<spring_boot_version>2.4.1</spring_boot_version>
</properties>
<dependencies>
<!-- Compile dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>${spring_boot_version}</version>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring_boot_version}</version>
<type>pom</type>
<scope>import</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.keycloak.bom</groupId>
<artifactId>keycloak-adapter-bom</artifactId>
<version>13.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>

</project>
125 changes: 125 additions & 0 deletions src/main/java/autoconfigure/KeycloakSecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package autoconfigure;

import org.keycloak.adapters.KeycloakConfigResolver;
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
import org.keycloak.adapters.springsecurity.client.KeycloakClientRequestFactory;
import org.keycloak.adapters.springsecurity.client.KeycloakRestTemplate;
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpMethod;
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.builders.WebSecurity;
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

import static org.springframework.http.HttpMethod.DELETE;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.http.HttpMethod.PUT;

@KeycloakConfiguration
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

private static final String CORS_ALLOWED_HEADERS = "origin,content-type,accept,x-requested-with,Authorization";

private String opensrpAllowedSources = "";

private long corsMaxAge = 60;

private static final Logger logger = LoggerFactory.getLogger(KeycloakSecurityConfig.class);

@Autowired
private KeycloakClientRequestFactory keycloakClientRequestFactory;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {

SimpleAuthorityMapper grantedAuthorityMapper = new SimpleAuthorityMapper();
grantedAuthorityMapper.setPrefix("ROLE_");

KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}

@Bean
public KeycloakConfigResolver keycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}

@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}

@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
logger.info("Inside configure method");
http.cors()
.and()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/home").permitAll()
.mvcMatchers("/logout.do").permitAll()
.antMatchers("/fhir/**")
.authenticated()
.and()
.csrf()
.ignoringAntMatchers("/fhir/**")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("logout.do", "GET"));

}

@Override
public void configure(WebSecurity web) throws Exception {
/* @formatter:off */
web.ignoring().mvcMatchers("/js/**")
.and().ignoring().mvcMatchers("/css/**")
.and().ignoring().mvcMatchers("/images/**")
.and().ignoring().mvcMatchers("/html/**")
.and().ignoring().antMatchers(HttpMethod.OPTIONS, "/**")
.and().ignoring().antMatchers("/home")
.and().ignoring().antMatchers("/*")
.and().ignoring().antMatchers("/fhir/metadata");
/* @formatter:on */
}

@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList(opensrpAllowedSources.split(",")));
configuration.setAllowedMethods(Arrays.asList(GET.name(), POST.name(), PUT.name(), DELETE.name()));
configuration.setAllowedHeaders(Arrays.asList(CORS_ALLOWED_HEADERS.split(",")));
configuration.setMaxAge(corsMaxAge);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public KeycloakRestTemplate keycloakRestTemplate() {
return new KeycloakRestTemplate(keycloakClientRequestFactory);
}

}
40 changes: 40 additions & 0 deletions src/main/java/autoconfigure/SecurityAutoConfiguration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package autoconfigure;

/*-
* #%L
* hapi-fhir-spring-boot-autoconfigure
* %%
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/

import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

/**
* {@link EnableAutoConfiguration Auto-configuration} for HAPI FHIR.
*
* @author Reham Muzzamil
*/
@Configuration
@AutoConfigureAfter({ KeycloakSecurityConfig.class })
@EnableWebSecurity
@Import({ KeycloakSecurityConfig.class })
public class SecurityAutoConfiguration {

}
1 change: 1 addition & 0 deletions src/main/resources/META-INF/spring.factories
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=autoconfigure.SecurityAutoConfiguration
4 changes: 4 additions & 0 deletions src/test/resources/logback-test.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
</configuration>

0 comments on commit a4b86ba

Please sign in to comment.