Skip to content

Commit

Permalink
Merge pull request #449 from RADAR-base/update-auth
Browse files Browse the repository at this point in the history
Update auth configuration
  • Loading branch information
mpgxvii authored Mar 14, 2024
2 parents ef8f222 + 0b90337 commit cecca7f
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 52 deletions.
5 changes: 2 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ apply plugin: 'io.spring.dependency-management'
apply plugin: 'scala'

group = 'org.radarbase'
version = '2.4.0'
version = '2.4.1'

java {
toolchain {
Expand All @@ -24,7 +24,6 @@ java {

repositories {
mavenCentral()
mavenLocal()
maven { url = "https://oss.sonatype.org/content/repositories/snapshots" }
}

Expand All @@ -39,7 +38,7 @@ ext {
springDocVersion = '2.2.0'
lombokVersion = '1.18.26'
junit5Version = '5.9.2'
radarSpringAuthVersion = '1.2.0'
radarSpringAuthVersion = '1.2.1'
springSecurityVersion = '6.0.2'
hibernateValidatorVersion = '8.0.0.Final'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.web.client.ResourceAccessException;

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
Expand Down Expand Up @@ -158,20 +159,23 @@ public void unauthorisedCreateNotificationsForUser() {
HttpEntity<FcmNotificationDto> notificationDtoHttpEntity =
new HttpEntity<>(fcmNotificationDto, HEADERS);

ResponseEntity<FcmNotificationDto> notificationDtoResponseEntity =
restTemplate.exchange(
createURLWithPort(
port,
ProjectEndpointAuthTest.PROJECT_PATH
+ UserEndpointAuthTest.DEFAULT_PROJECT
+ UserEndpointAuthTest.USER_PATH
+ DEFAULT_USER
+ NOTIFICATION_PATH),
HttpMethod.POST,
notificationDtoHttpEntity,
FcmNotificationDto.class);

assertEquals(HttpStatus.UNAUTHORIZED, notificationDtoResponseEntity.getStatusCode());
ResponseEntity<FcmNotificationDto> notificationDtoResponseEntity = null;
try {
notificationDtoResponseEntity =
restTemplate.exchange(
createURLWithPort(
port,
ProjectEndpointAuthTest.PROJECT_PATH
+ UserEndpointAuthTest.DEFAULT_PROJECT
+ UserEndpointAuthTest.USER_PATH
+ DEFAULT_USER
+ NOTIFICATION_PATH),
HttpMethod.POST,
notificationDtoHttpEntity,
FcmNotificationDto.class);
} catch (ResourceAccessException e) {
assertEquals(notificationDtoResponseEntity, null);
}
}

@Test
Expand Down Expand Up @@ -295,4 +299,4 @@ public void forbiddenViewNotificationsForOtherProject() {

assertEquals(HttpStatus.UNAUTHORIZED, notificationDtoResponseEntity.getStatusCode());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,12 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.web.client.ResourceAccessException;

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestMethodOrder(OrderAnnotation.class)
@SuppressWarnings("PMD.DataflowAnomalyAnalysis")
public class ProjectEndpointAuthTest {

public static final String PROJECT_PATH = "/projects";
Expand All @@ -70,13 +72,17 @@ public void unauthorisedCreateProject() {
ProjectDto projectDto = new ProjectDto().setProjectId("radar");
HttpEntity<ProjectDto> projectEntity = new HttpEntity<>(projectDto, HEADERS);

ResponseEntity<ProjectDto> responseEntity =
restTemplate.exchange(
createURLWithPort(port, PROJECT_PATH),
HttpMethod.POST,
projectEntity,
ProjectDto.class);
assertEquals(HttpStatus.UNAUTHORIZED, responseEntity.getStatusCode());
ResponseEntity<ProjectDto> responseEntity = null;
try {
responseEntity =
restTemplate.exchange(
createURLWithPort(port, PROJECT_PATH),
HttpMethod.POST,
projectEntity,
ProjectDto.class);
} catch (ResourceAccessException e) {
assertEquals(responseEntity, null);
}
}

@Test
Expand Down Expand Up @@ -167,4 +173,4 @@ public void getForbiddenProjectWithAuth() {
// Access denied as the user has only access to the project that it is part of.
assertEquals(HttpStatus.FORBIDDEN, responseEntity.getStatusCode());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.web.client.ResourceAccessException;

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
Expand Down Expand Up @@ -109,15 +110,18 @@ public void unauthorisedViewSingleUser() {
public void unauthorisedCreateUser() {
HttpEntity<FcmUserDto> userDtoHttpEntity = new HttpEntity<>(userDto, HEADERS);

ResponseEntity<FcmUserDto> responseEntity =
restTemplate.exchange(
createURLWithPort(
port, ProjectEndpointAuthTest.PROJECT_PATH + DEFAULT_PROJECT + USER_PATH),
HttpMethod.POST,
userDtoHttpEntity,
FcmUserDto.class);

assertEquals(HttpStatus.UNAUTHORIZED, responseEntity.getStatusCode());
ResponseEntity<FcmUserDto> responseEntity = null;
try {
responseEntity =
restTemplate.exchange(
createURLWithPort(
port, ProjectEndpointAuthTest.PROJECT_PATH + DEFAULT_PROJECT + USER_PATH),
HttpMethod.POST,
userDtoHttpEntity,
FcmUserDto.class);
} catch (ResourceAccessException e) {
assertEquals(responseEntity, null);
}
}

@Test
Expand Down Expand Up @@ -202,4 +206,4 @@ public void viewAllUsers() {
// This should return a filtered list of users for which the token has access.
assertEquals(HttpStatus.OK, responseEntity.getStatusCode());
}
}
}
4 changes: 2 additions & 2 deletions src/integrationTest/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ spring.jpa.hibernate.ddl-auto=none
spring.datasource.username=postgres
spring.datasource.password=radar
spring.datasource.url=jdbc:postgresql://localhost:5432/radar
#jdbc:hsqldb:hsql://localhost:9001/appserver for running hsql separately in dev or testing
# jdbc:hsqldb:hsql://localhost:9001/appserver for running hsql separately in dev or testing
spring.jpa.properties.hibernate.jdbc.time_zone=UTC
spring.jpa.properties.hibernate.generate_statistics=false
spring.jpa.properties.hibernate.jdbc.batch_size=20
Expand Down Expand Up @@ -87,7 +87,7 @@ spring.datasource.hikari.leakDetectionThreshold=120000
# OAuth2 Resource Server Security
security.oauth2.resource.id=res_AppServer
security.radar.managementportal.enabled=true
security.radar.managementportal.url=http://localhost:8081
security.radar.managementportal.url=http://localhost:8081/managementportal
# OAuth2 Client Security
#security.oauth2.client.clientId=
#security.oauth2.client.clientSecret=
Expand Down
18 changes: 4 additions & 14 deletions src/main/java/org/radarbase/appserver/config/AuthConfig.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package org.radarbase.appserver.config;

import lombok.extern.slf4j.Slf4j;
import org.radarbase.auth.config.TokenValidatorConfig;
import org.radarbase.auth.config.TokenVerifierPublicKeyConfig;
import org.radarbase.auth.exception.ConfigurationException;
import org.radarbase.auth.token.RadarToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
Expand Down Expand Up @@ -32,7 +29,8 @@ public class AuthConfig {

@Bean
public ManagementPortalAuthProperties getAuthProperties() {
return new ManagementPortalAuthProperties(baseUrl, resourceName);
TokenVerifierPublicKeyConfig validatorConfig = TokenVerifierPublicKeyConfig.readFromFileOrClasspath();
return new ManagementPortalAuthProperties(baseUrl, resourceName, validatorConfig.getPublicKeyEndpoints());
}

/**
Expand All @@ -45,15 +43,7 @@ public ManagementPortalAuthProperties getAuthProperties() {
@Bean
AuthValidator<RadarToken> getAuthValidator(
@Autowired ManagementPortalAuthProperties managementPortalAuthProperties) {
try {
TokenValidatorConfig validatorConfig = TokenVerifierPublicKeyConfig.readFromFileOrClasspath();
return new ManagementPortalAuthValidator(managementPortalAuthProperties, validatorConfig);
} catch (ConfigurationException exc) {
log.warn(
"Could not loading config from RADAR_IS file. Now using default public key "
+ "endpoint...");
return new ManagementPortalAuthValidator(managementPortalAuthProperties);
}
return new ManagementPortalAuthValidator(managementPortalAuthProperties);
}

@Bean
Expand All @@ -80,4 +70,4 @@ public interface AuthPermissions {
String CREATE = "CREATE";
String UPDATE = "UPDATE";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package org.radarbase.appserver.config;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Created by dverbeec on 14/06/2017.
*/
@SuppressWarnings("PMD.DataflowAnomalyAnalysis")
public class TokenVerifierPublicKeyConfig {

private static final Logger log = LoggerFactory.getLogger(TokenVerifierPublicKeyConfig.class);

public static final String LOCATION_ENV = "RADAR_IS_CONFIG_LOCATION";

private static final String CONFIG_FILE_NAME = "radar-is.yml";

private transient List<URI> publicKeyEndpoints = new LinkedList<>();

private transient String resourceName;

/**
* Read the configuration from file. This method will first check if the environment variable
* <code>RADAR_IS_CONFIG_LOCATION</code> is set. If not set, it will look for a file called
* <code>radar_is.yml</code> on the classpath. The configuration will be kept in a static field,
* so subsequent calls to this method will return the same object.
*
* @return The initialized configuration object based on the contents of the configuration file
* @throws RuntimException If there is any problem loading the configuration
*/
public static TokenVerifierPublicKeyConfig readFromFileOrClasspath() {
String customLocation = System.getenv(LOCATION_ENV);
URL configFile;
if (customLocation != null) {
log.info(LOCATION_ENV + " environment variable set, loading config from {}",
customLocation);
try {
configFile = new File(customLocation).toURI().toURL();
} catch (MalformedURLException ex) {
throw new RuntimeException(ex);
}
} else {
// if config location not defined, look for it on the classpath
log.info(LOCATION_ENV
+ " environment variable not set, looking for it on the classpath");
configFile = Thread.currentThread().getContextClassLoader()
.getResource(CONFIG_FILE_NAME);

if (configFile == null) {
throw new RuntimeException(
"Cannot find " + CONFIG_FILE_NAME + " file in classpath. ");
}
}
log.info("Config file found at {}", configFile.getPath());

ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
try (InputStream stream = configFile.openStream()) {
return mapper.readValue(stream, TokenVerifierPublicKeyConfig.class);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}

public List<URI> getPublicKeyEndpoints() {
return publicKeyEndpoints;
}

public String getResourceName() {
return resourceName;
}

}

0 comments on commit cecca7f

Please sign in to comment.