Removed the example-microservice.
Signed-off-by: kvanmaasdam <K.vanMaasdam@student.tudelft.nl>
This commit is contained in:
parent
4b22198c04
commit
72ee9aa06f
23 changed files with 1 additions and 1036 deletions
|
@ -1,69 +0,0 @@
|
|||
image: gradle:6.7-jdk15
|
||||
|
||||
stages:
|
||||
- build
|
||||
- staticAnalysis
|
||||
- test
|
||||
|
||||
variables:
|
||||
# Disable the Gradle daemon to ensure isolated runs of the CI pipeline.
|
||||
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
|
||||
|
||||
# Default build cache settings to extend from
|
||||
.build_cached:
|
||||
cache:
|
||||
key: "gradle-build"
|
||||
paths:
|
||||
# Only cache the gradle directory, as we do not use a shared cache
|
||||
- .gradle/
|
||||
policy: pull
|
||||
|
||||
build-example-microservice:
|
||||
extends:
|
||||
- .build_cached
|
||||
needs:
|
||||
- gradle_build
|
||||
dependencies:
|
||||
- gradle_build
|
||||
stage: build
|
||||
script:
|
||||
gradle example-microservice:assemble example-microservice:testClasses
|
||||
|
||||
checkStyle-example-microservice:
|
||||
extends:
|
||||
- .build_cached
|
||||
needs:
|
||||
- gradle_build
|
||||
dependencies:
|
||||
- gradle_build
|
||||
stage: staticAnalysis
|
||||
script:
|
||||
gradle example-microservice:checkstyleMain example-microservice:checkStyleTest
|
||||
allow_failure: true
|
||||
|
||||
|
||||
PMD-example-microservice:
|
||||
extends:
|
||||
- .build_cached
|
||||
needs:
|
||||
- gradle_build
|
||||
dependencies:
|
||||
- gradle_build
|
||||
stage: staticAnalysis
|
||||
script:
|
||||
gradle example-microservice:pmdMain
|
||||
allow_failure: true
|
||||
|
||||
test-example-microservice:
|
||||
extends:
|
||||
- .build_cached
|
||||
needs:
|
||||
- gradle_build
|
||||
dependencies:
|
||||
- gradle_build
|
||||
stage: test
|
||||
script:
|
||||
- gradle example-microservice:test example-microservice:jacocoTestReport
|
||||
- cat example-microservice/build/reports/jacoco/test/html/index.html | grep -Po "Total.*?([0-9]{1,3})%"
|
||||
coverage: /([0-9]{1,3})%/
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
//Needed only for SNAPSHOT versions
|
||||
//maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
|
||||
}
|
||||
dependencies {
|
||||
classpath 'info.solidsoft.gradle.pitest:gradle-pitest-plugin:1.5.2'
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.4.13'
|
||||
id 'io.spring.dependency-management' version '1.1.4'
|
||||
id 'java'
|
||||
// Test coverage
|
||||
id 'jacoco'
|
||||
|
||||
// Code style
|
||||
id 'checkstyle'
|
||||
|
||||
// PMD
|
||||
id 'pmd'
|
||||
|
||||
// PITest
|
||||
id 'info.solidsoft.pitest' version '1.5.2'
|
||||
}
|
||||
|
||||
group = 'nl.tudelft.cse.sem.template'
|
||||
version = '0.0.1-SNAPSHOT'
|
||||
sourceCompatibility = 15
|
||||
targetCompatibility = 15
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
compileOnly 'org.projectlombok:lombok:1.18.24'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.24'
|
||||
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
|
||||
implementation 'org.springframework.boot:spring-boot-starter'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt
|
||||
implementation 'io.jsonwebtoken:jjwt:0.9.1'
|
||||
|
||||
|
||||
// Local test database (in-memory)
|
||||
implementation 'com.h2database:h2'
|
||||
developmentOnly 'org.hibernate:hibernate-entitymanager'
|
||||
|
||||
testImplementation('org.springframework.boot:spring-boot-starter-test') {
|
||||
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
|
||||
}
|
||||
testImplementation('org.junit.jupiter:junit-jupiter:5.8.2')
|
||||
testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.12.4'
|
||||
testImplementation('org.assertj:assertj-core:3.23.1')
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
jacoco {
|
||||
enabled = true
|
||||
includes = ['nl.tudelft.sem.template.*']
|
||||
excludes = []
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
jacoco {
|
||||
toolVersion = "0.8.7" // Use the desired version of JaCoCo
|
||||
}
|
||||
|
||||
jacocoTestCoverageVerification() {
|
||||
dependsOn test
|
||||
violationRules {
|
||||
rule {
|
||||
enabled = true
|
||||
element = 'CLASS'
|
||||
includes = ['nl.tudelft.sem.template.*']
|
||||
|
||||
limit {
|
||||
counter = 'BRANCH'
|
||||
value = 'COVEREDRATIO'
|
||||
minimum = 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkstyle {
|
||||
toolVersion "10.12.5"
|
||||
configFile = file("${rootDir}/config/checkstyle/checkstyle.xml")
|
||||
ignoreFailures = false
|
||||
maxErrors = 0
|
||||
maxWarnings = 0
|
||||
}
|
||||
|
||||
pmd {
|
||||
incrementalAnalysis = true
|
||||
sourceSets = [sourceSets.main]
|
||||
}
|
||||
|
||||
apply plugin: 'info.solidsoft.pitest'
|
||||
pitest {
|
||||
//adds dependency to org.pitest:pitest-junit5-plugin and sets "testPlugin" to "junit5"
|
||||
junit5PluginVersion = '0.12'
|
||||
|
||||
targetClasses = ['nl.tudelft.sem.template.*'] //by default "${project.group}.*"
|
||||
pitestVersion = '1.5.1' //not needed when a default PIT version should be used
|
||||
threads = 4
|
||||
outputFormats = ['XML', 'HTML']
|
||||
timestampedReports = false
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
rootProject.name = 'example-microservice'
|
|
@ -1,14 +0,0 @@
|
|||
package nl.tudelft.sem.template.example;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* Example microservice application.
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.authentication;
|
||||
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Authentication Manager.
|
||||
*/
|
||||
@Component
|
||||
public class AuthManager {
|
||||
/**
|
||||
* Interfaces with spring security to get the name of the user in the current context.
|
||||
*
|
||||
* @return The name of the user.
|
||||
*/
|
||||
public String getNetId() {
|
||||
return SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.authentication;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Authentication entry point for JWT security.
|
||||
* <p>
|
||||
* The authentication entry point is called when an unauthenticated client tries to access a protected resource.
|
||||
* This JWT authentication entry point returns a response indicating the request was unauthorized.
|
||||
* </p>
|
||||
*/
|
||||
@Component
|
||||
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException authException)
|
||||
throws IOException, ServletException {
|
||||
|
||||
// Return an unauthorized response code
|
||||
response.addHeader(JwtRequestFilter.WWW_AUTHENTICATE_HEADER, JwtRequestFilter.AUTHORIZATION_AUTH_SCHEME);
|
||||
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.authentication;
|
||||
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import io.jsonwebtoken.JwtException;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
* Request filter for JWT security.
|
||||
* <p>
|
||||
* The request filter is called once for each request and makes it possible to modify the request
|
||||
* before it reaches the application. If an authorization header is present in the request,
|
||||
* the filter will validate it and authenticate the token.
|
||||
* </p>
|
||||
*/
|
||||
@Component
|
||||
public class JwtRequestFilter extends OncePerRequestFilter {
|
||||
|
||||
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||
public static final String WWW_AUTHENTICATE_HEADER = "WWW-Authenticate";
|
||||
public static final String AUTHORIZATION_AUTH_SCHEME = "Bearer";
|
||||
|
||||
private final transient JwtTokenVerifier jwtTokenVerifier;
|
||||
|
||||
@Autowired
|
||||
public JwtRequestFilter(JwtTokenVerifier jwtTokenVerifier) {
|
||||
this.jwtTokenVerifier = jwtTokenVerifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* This filter will verify and authenticate a JWT token if a valid authorization header is set.
|
||||
*
|
||||
* @param request The current request we are handling.
|
||||
* @param response The current response we are building.
|
||||
* @param filterChain The next link in the filter chain.
|
||||
* @throws ServletException Exception.
|
||||
* @throws IOException Exception
|
||||
*/
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
|
||||
// Get authorization header
|
||||
String authorizationHeader = request.getHeader(AUTHORIZATION_HEADER);
|
||||
|
||||
// Check if an authorization header is set
|
||||
if (authorizationHeader != null) {
|
||||
String[] directives = authorizationHeader.split(" ");
|
||||
|
||||
// Check for the correct auth scheme
|
||||
if (directives.length == 2 && directives[0].equals(AUTHORIZATION_AUTH_SCHEME)) {
|
||||
String token = directives[1];
|
||||
|
||||
try {
|
||||
if (jwtTokenVerifier.validateToken(token)) {
|
||||
String netId = jwtTokenVerifier.getNetIdFromToken(token);
|
||||
var authenticationToken = new UsernamePasswordAuthenticationToken(
|
||||
netId,
|
||||
null, List.of() // no credentials and no authorities
|
||||
);
|
||||
authenticationToken.setDetails(new WebAuthenticationDetailsSource()
|
||||
.buildDetails(request));
|
||||
|
||||
// After setting the Authentication in the context, we specify
|
||||
// that the current user is authenticated. So it passes the
|
||||
// Spring Security Configurations successfully.
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||
}
|
||||
|
||||
} catch (ExpiredJwtException e) {
|
||||
System.err.println("JWT token has expired.");
|
||||
} catch (IllegalArgumentException | JwtException e) {
|
||||
System.err.println("Unable to parse JWT token");
|
||||
}
|
||||
}
|
||||
System.err.println("Invalid authorization header");
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.authentication;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import java.util.Date;
|
||||
import java.util.function.Function;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Verifies the JWT token in the request for validity.
|
||||
*/
|
||||
@Component
|
||||
public class JwtTokenVerifier {
|
||||
@Value("${jwt.secret}") // automatically loads jwt.secret from resources/application.properties
|
||||
private transient String jwtSecret;
|
||||
|
||||
/**
|
||||
* Validate the JWT token for expiration.
|
||||
*/
|
||||
public boolean validateToken(String token) {
|
||||
return !isTokenExpired(token);
|
||||
}
|
||||
|
||||
public String getNetIdFromToken(String token) {
|
||||
return getClaimFromToken(token, Claims::getSubject);
|
||||
}
|
||||
|
||||
public Date getExpirationDateFromToken(String token) {
|
||||
return getClaimFromToken(token, Claims::getExpiration);
|
||||
}
|
||||
|
||||
private Boolean isTokenExpired(String token) {
|
||||
final Date expiration = getExpirationDateFromToken(token);
|
||||
return expiration.before(new Date());
|
||||
}
|
||||
|
||||
private <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
|
||||
final Claims claims = getClaims(token);
|
||||
return claimsResolver.apply(claims);
|
||||
}
|
||||
|
||||
private Claims getClaims(String token) {
|
||||
return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody();
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.config;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import lombok.Getter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
|
||||
/**
|
||||
* The H2 config.
|
||||
*/
|
||||
@Configuration
|
||||
@EnableJpaRepositories("nl.tudelft.sem.template.example.domain")
|
||||
@PropertySource("classpath:application-dev.properties")
|
||||
@EnableTransactionManagement
|
||||
public class H2Config {
|
||||
|
||||
@Getter
|
||||
private final Environment environment;
|
||||
|
||||
public H2Config(Environment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the connection to the database.
|
||||
*
|
||||
* @return The data source.
|
||||
*/
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
DriverManagerDataSource dataSource = new DriverManagerDataSource();
|
||||
dataSource.setDriverClassName(environment.getProperty("jdbc.driverClassName"));
|
||||
dataSource.setUrl(environment.getProperty("jdbc.url"));
|
||||
dataSource.setUsername(environment.getProperty("jdbc.user"));
|
||||
dataSource.setPassword(environment.getProperty("jdbc.pass"));
|
||||
|
||||
return dataSource;
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.config;
|
||||
|
||||
import nl.tudelft.sem.template.example.authentication.JwtAuthenticationEntryPoint;
|
||||
import nl.tudelft.sem.template.example.authentication.JwtRequestFilter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
/**
|
||||
* The type Web security config.
|
||||
*/
|
||||
@Configuration
|
||||
public class RequestAuthenticationConfig extends WebSecurityConfigurerAdapter {
|
||||
private final transient JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
|
||||
private final transient JwtRequestFilter jwtRequestFilter;
|
||||
|
||||
public RequestAuthenticationConfig(JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint,
|
||||
JwtRequestFilter jwtRequestFilter) {
|
||||
this.jwtAuthenticationEntryPoint = jwtAuthenticationEntryPoint;
|
||||
this.jwtRequestFilter = jwtRequestFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.csrf().disable()
|
||||
.authorizeRequests()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
|
||||
.and()
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.controllers;
|
||||
|
||||
import nl.tudelft.sem.template.example.authentication.AuthManager;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Hello World example controller.
|
||||
* <p>
|
||||
* This controller shows how you can extract information from the JWT token.
|
||||
* </p>
|
||||
*/
|
||||
@RestController
|
||||
public class DefaultController {
|
||||
|
||||
private final transient AuthManager authManager;
|
||||
|
||||
/**
|
||||
* Instantiates a new controller.
|
||||
*
|
||||
* @param authManager Spring Security component used to authenticate and authorize the user
|
||||
*/
|
||||
@Autowired
|
||||
public DefaultController(AuthManager authManager) {
|
||||
this.authManager = authManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets example by id.
|
||||
*
|
||||
* @return the example found in the database with the given id
|
||||
*/
|
||||
@GetMapping("/hello")
|
||||
public ResponseEntity<String> helloWorld() {
|
||||
return ResponseEntity.ok("Hello " + authManager.getNetId());
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
# Database configuration
|
||||
jdbc.driverClassName=org.h2.Driver
|
||||
jdbc.url=jdbc:h2:./example-microservice/example;DB_CLOSE_ON_EXIT=FALSE
|
||||
|
||||
# Hibernate configuration
|
||||
spring.jpa.hibernate.ddl-auto=create-drop
|
||||
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||
hibernate.hbm2ddl.auto=create
|
|
@ -1,5 +0,0 @@
|
|||
# Port of the microservice
|
||||
server.port=8082
|
||||
|
||||
# Secret for the JWT signing
|
||||
jwt.secret=exampleSecret
|
|
@ -1,38 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
/**
|
||||
* Tests for the AuthManager class.
|
||||
*/
|
||||
public class AuthManagerTests {
|
||||
private transient AuthManager authManager;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
authManager = new AuthManager();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNetidTest() {
|
||||
// Arrange
|
||||
String expected = "user123";
|
||||
var authenticationToken = new UsernamePasswordAuthenticationToken(
|
||||
expected,
|
||||
null, List.of() // no credentials and no authorities
|
||||
);
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||
|
||||
// Act
|
||||
String actual = authManager.getNetId();
|
||||
|
||||
// Assert
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.authentication;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
/**
|
||||
* Tests for the JwtAuthenticationEntryPoint class.
|
||||
*/
|
||||
public class JwtAuthenticationEntryPointTests {
|
||||
private transient JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
|
||||
|
||||
private transient HttpServletRequest mockRequest;
|
||||
private transient HttpServletResponse mockResponse;
|
||||
private transient AuthenticationException dummyAuthenticationException;
|
||||
|
||||
/**
|
||||
* Set up mocks.
|
||||
*/
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
mockRequest = Mockito.mock(HttpServletRequest.class);
|
||||
mockResponse = Mockito.mock(HttpServletResponse.class);
|
||||
dummyAuthenticationException = Mockito.mock(AuthenticationException.class);
|
||||
|
||||
jwtAuthenticationEntryPoint = new JwtAuthenticationEntryPoint();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void commenceTest() throws ServletException, IOException {
|
||||
// Act
|
||||
jwtAuthenticationEntryPoint.commence(mockRequest, mockResponse, dummyAuthenticationException);
|
||||
|
||||
// Assert
|
||||
verifyNoInteractions(mockRequest);
|
||||
verify(mockResponse).addHeader(JwtRequestFilter.WWW_AUTHENTICATE_HEADER,
|
||||
JwtRequestFilter.AUTHORIZATION_AUTH_SCHEME);
|
||||
verify(mockResponse).sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
|
||||
verifyNoMoreInteractions(mockResponse);
|
||||
}
|
||||
}
|
|
@ -1,171 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import io.jsonwebtoken.JwtException;
|
||||
import java.io.IOException;
|
||||
import java.util.stream.Stream;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
/**
|
||||
* Tests for the JwtRequestFilter class.
|
||||
*/
|
||||
public class JwtRequestFilterTests {
|
||||
private transient JwtRequestFilter jwtRequestFilter;
|
||||
|
||||
private transient HttpServletRequest mockRequest;
|
||||
private transient HttpServletResponse mockResponse;
|
||||
private transient FilterChain mockFilterChain;
|
||||
|
||||
private transient JwtTokenVerifier mockJwtTokenVerifier;
|
||||
|
||||
/**
|
||||
* Set up mocks.
|
||||
*/
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
mockRequest = Mockito.mock(HttpServletRequest.class);
|
||||
mockResponse = Mockito.mock(HttpServletResponse.class);
|
||||
mockFilterChain = Mockito.mock(FilterChain.class);
|
||||
mockJwtTokenVerifier = Mockito.mock(JwtTokenVerifier.class);
|
||||
|
||||
jwtRequestFilter = new JwtRequestFilter(mockJwtTokenVerifier);
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(null);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void assertChainContinues() throws ServletException, IOException {
|
||||
verify(mockFilterChain).doFilter(mockRequest, mockResponse);
|
||||
verifyNoMoreInteractions(mockFilterChain);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctToken() throws ServletException, IOException {
|
||||
// Arrange
|
||||
String token = "randomtoken123";
|
||||
String user = "user123";
|
||||
when(mockRequest.getHeader("Authorization")).thenReturn("Bearer " + token);
|
||||
when(mockJwtTokenVerifier.validateToken(token)).thenReturn(true);
|
||||
when(mockJwtTokenVerifier.getNetIdFromToken(token)).thenReturn(user);
|
||||
|
||||
// Act
|
||||
jwtRequestFilter.doFilterInternal(mockRequest, mockResponse, mockFilterChain);
|
||||
|
||||
// Assert
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication().getName())
|
||||
.isEqualTo(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidToken() throws ServletException, IOException {
|
||||
// Arrange
|
||||
String token = "randomtoken123";
|
||||
String user = "user123";
|
||||
when(mockRequest.getHeader("Authorization")).thenReturn("Bearer " + token);
|
||||
when(mockJwtTokenVerifier.validateToken(token)).thenReturn(false);
|
||||
when(mockJwtTokenVerifier.getNetIdFromToken(token)).thenReturn(user);
|
||||
|
||||
// Act
|
||||
jwtRequestFilter.doFilterInternal(mockRequest, mockResponse, mockFilterChain);
|
||||
|
||||
// Assert
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication())
|
||||
.isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameterized test for various token verification exceptions.
|
||||
*
|
||||
* @param throwable the exception to be tested
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("tokenVerificationExceptionGenerator")
|
||||
public void tokenVerificationException(Class<? extends Throwable> throwable)
|
||||
throws ServletException, IOException {
|
||||
// Arrange
|
||||
String token = "randomtoken123";
|
||||
String user = "user123";
|
||||
when(mockRequest.getHeader("Authorization")).thenReturn("Bearer " + token);
|
||||
when(mockJwtTokenVerifier.validateToken(token)).thenThrow(throwable);
|
||||
when(mockJwtTokenVerifier.getNetIdFromToken(token)).thenReturn(user);
|
||||
|
||||
// Act
|
||||
jwtRequestFilter.doFilterInternal(mockRequest, mockResponse, mockFilterChain);
|
||||
|
||||
// Assert
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication())
|
||||
.isNull();
|
||||
}
|
||||
|
||||
private static Stream<Arguments> tokenVerificationExceptionGenerator() {
|
||||
return Stream.of(
|
||||
Arguments.of(ExpiredJwtException.class),
|
||||
Arguments.of(IllegalArgumentException.class),
|
||||
Arguments.of(JwtException.class)
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullToken() throws ServletException, IOException {
|
||||
// Arrange
|
||||
when(mockRequest.getHeader("Authorization")).thenReturn(null);
|
||||
|
||||
// Act
|
||||
jwtRequestFilter.doFilterInternal(mockRequest, mockResponse, mockFilterChain);
|
||||
|
||||
// Assert
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication())
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidPrefix() throws ServletException, IOException {
|
||||
// Arrange
|
||||
String token = "randomtoken123";
|
||||
String user = "user123";
|
||||
when(mockRequest.getHeader("Authorization")).thenReturn("Bearer1 " + token);
|
||||
when(mockJwtTokenVerifier.validateToken(token)).thenReturn(true);
|
||||
when(mockJwtTokenVerifier.getNetIdFromToken(token)).thenReturn(user);
|
||||
|
||||
// Act
|
||||
jwtRequestFilter.doFilterInternal(mockRequest, mockResponse, mockFilterChain);
|
||||
|
||||
// Assert
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication())
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noPrefix() throws ServletException, IOException {
|
||||
// Arrange
|
||||
String token = "randomtoken123";
|
||||
String user = "user123";
|
||||
when(mockRequest.getHeader("Authorization")).thenReturn(token);
|
||||
when(mockJwtTokenVerifier.validateToken(token)).thenReturn(true);
|
||||
when(mockJwtTokenVerifier.getNetIdFromToken(token)).thenReturn(user);
|
||||
|
||||
// Act
|
||||
jwtRequestFilter.doFilterInternal(mockRequest, mockResponse, mockFilterChain);
|
||||
|
||||
// Assert
|
||||
assertThat(SecurityContextHolder.getContext().getAuthentication())
|
||||
.isNull();
|
||||
}
|
||||
}
|
|
@ -1,110 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.MalformedJwtException;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.SignatureException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.assertj.core.api.ThrowableAssert;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests for the JwtTokenVerifier class.
|
||||
*/
|
||||
public class JwtTokenVerifierTests {
|
||||
private transient JwtTokenVerifier jwtTokenVerifier;
|
||||
|
||||
private final String secret = "testSecret123";
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws NoSuchFieldException, IllegalAccessException {
|
||||
jwtTokenVerifier = new JwtTokenVerifier();
|
||||
this.injectSecret(secret);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateNonExpiredToken() {
|
||||
// Arrange
|
||||
String token = generateToken(secret, "user123", -10_000_000, 10_000_000);
|
||||
|
||||
// Act
|
||||
boolean actual = jwtTokenVerifier.validateToken(token);
|
||||
|
||||
// Assert
|
||||
assertThat(actual).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateExpiredToken() {
|
||||
// Arrange
|
||||
String token = generateToken(secret, "user123", -10_000_000, -5_000_000);
|
||||
|
||||
// Act
|
||||
ThrowableAssert.ThrowingCallable action = () -> jwtTokenVerifier.validateToken(token);
|
||||
|
||||
// Assert
|
||||
assertThatExceptionOfType(ExpiredJwtException.class)
|
||||
.isThrownBy(action);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateTokenIncorrectSignature() {
|
||||
// Arrange
|
||||
String token = generateToken("incorrectSecret", "user123", -10_000_000, 10_000_000);
|
||||
|
||||
// Act
|
||||
ThrowableAssert.ThrowingCallable action = () -> jwtTokenVerifier.validateToken(token);
|
||||
|
||||
// Assert
|
||||
assertThatExceptionOfType(SignatureException.class)
|
||||
.isThrownBy(action);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateMalformedToken() {
|
||||
// Arrange
|
||||
String token = "malformedtoken";
|
||||
|
||||
// Act
|
||||
ThrowableAssert.ThrowingCallable action = () -> jwtTokenVerifier.validateToken(token);
|
||||
|
||||
// Assert
|
||||
assertThatExceptionOfType(MalformedJwtException.class)
|
||||
.isThrownBy(action);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseNetid() {
|
||||
// Arrange
|
||||
String expected = "user123";
|
||||
String token = generateToken(secret, expected, -10_000_000, 10_000_000);
|
||||
|
||||
// Act
|
||||
String actual = jwtTokenVerifier.getNetIdFromToken(token);
|
||||
|
||||
// Assert
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
private String generateToken(String jwtSecret, String netid, long issuanceOffset, long expirationOffset) {
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
return Jwts.builder().setClaims(claims).setSubject(netid)
|
||||
.setIssuedAt(new Date(System.currentTimeMillis() + issuanceOffset))
|
||||
.setExpiration(new Date(System.currentTimeMillis() + expirationOffset))
|
||||
.signWith(SignatureAlgorithm.HS512, jwtSecret).compact();
|
||||
}
|
||||
|
||||
private void injectSecret(String secret) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field declaredField = jwtTokenVerifier.getClass().getDeclaredField("jwtSecret");
|
||||
declaredField.setAccessible(true);
|
||||
declaredField.set(jwtTokenVerifier, secret);
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.integration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import nl.tudelft.sem.template.example.authentication.AuthManager;
|
||||
import nl.tudelft.sem.template.example.authentication.JwtTokenVerifier;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.ResultActions;
|
||||
|
||||
/**
|
||||
* Integration tests for the example microservice.
|
||||
*/
|
||||
@SpringBootTest
|
||||
@ExtendWith(SpringExtension.class)
|
||||
// activate profiles to have spring use mocks during auto-injection of certain beans.
|
||||
@ActiveProfiles({"test", "mockTokenVerifier", "mockAuthenticationManager"})
|
||||
//@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
|
||||
@AutoConfigureMockMvc
|
||||
public class ExampleTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private transient JwtTokenVerifier mockJwtTokenVerifier;
|
||||
|
||||
@Autowired
|
||||
private transient AuthManager mockAuthenticationManager;
|
||||
|
||||
|
||||
@Test
|
||||
public void helloWorld() throws Exception {
|
||||
// Arrange
|
||||
// Notice how some custom parts of authorisation need to be mocked.
|
||||
// Otherwise, the integration test would never be able to authorise as the authorisation server is offline.
|
||||
when(mockAuthenticationManager.getNetId()).thenReturn("ExampleUser");
|
||||
when(mockJwtTokenVerifier.validateToken(anyString())).thenReturn(true);
|
||||
when(mockJwtTokenVerifier.getNetIdFromToken(anyString())).thenReturn("ExampleUser");
|
||||
|
||||
// Act
|
||||
// Still include Bearer token as AuthFilter itself is not mocked
|
||||
ResultActions result = mockMvc.perform(get("/hello")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "Bearer MockedToken"));
|
||||
|
||||
// Assert
|
||||
result.andExpect(status().isOk());
|
||||
|
||||
String response = result.andReturn().getResponse().getContentAsString();
|
||||
|
||||
assertThat(response).isEqualTo("Hello ExampleUser");
|
||||
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.profiles;
|
||||
|
||||
import nl.tudelft.sem.template.example.authentication.AuthManager;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
|
||||
/**
|
||||
* A configuration profile to allow injection of a mock AuthenticationManager.
|
||||
* A configuration can be used to define beans to be used during injection.
|
||||
* When this profile is active spring dependency injection will use this class to look for bean methods.
|
||||
* It will then prioritise these beans due to their @Primary tag.
|
||||
* In this case we return a mock to allow for more testability.
|
||||
* .
|
||||
* The profile tag will give a name to this configuration.
|
||||
* With the tag applied the profile will be inactive by default unless activated.
|
||||
* When the profile is active its bean will be used when looking for Beans to auto-inject.
|
||||
*/
|
||||
@Profile("mockAuthenticationManager")
|
||||
@Configuration
|
||||
public class MockAuthenticationManagerProfile {
|
||||
|
||||
/**
|
||||
* Mocks the AuthenticationManager.
|
||||
*
|
||||
* @return A mocked AuthenticationManager.
|
||||
*/
|
||||
@Bean
|
||||
@Primary // marks this bean as the first bean to use when trying to inject an AuthenticationManager
|
||||
public AuthManager getMockAuthenticationManager() {
|
||||
return Mockito.mock(AuthManager.class);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
package nl.tudelft.sem.template.example.profiles;
|
||||
|
||||
import nl.tudelft.sem.template.example.authentication.JwtTokenVerifier;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
|
||||
/**
|
||||
* A configuration profile to allow injection of a mock TokenVerifier.
|
||||
* A configuration can be used to define beans to be used during injection.
|
||||
* When this profile is active spring dependency injection will use this class to look for bean methods.
|
||||
* It will then prioritise these beans due to their @Primary tag.
|
||||
* In this case we return a mock to allow for more testability.
|
||||
* .
|
||||
* The profile tag will give a name to this configuration.
|
||||
* With the tag applied the profile will be inactive by default unless activated.
|
||||
* When the profile is active its bean will be used when looking for Beans to auto-inject.
|
||||
*/
|
||||
@Profile("mockTokenVerifier")
|
||||
@Configuration
|
||||
public class MockTokenVerifierProfile {
|
||||
|
||||
/**
|
||||
* Mocks the TokenVerifier.
|
||||
*
|
||||
* @return A mocked TokenVerifier.
|
||||
*/
|
||||
@Bean
|
||||
@Primary // marks this bean as the first bean to use when trying to inject an AuthenticationManager
|
||||
public JwtTokenVerifier getMockTokenVerifier() {
|
||||
return Mockito.mock(JwtTokenVerifier.class);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
rootProject.name = 'template'
|
||||
|
||||
include 'example-microservice'
|
||||
include 'order-microservice'
|
||||
include 'order-microservice'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue