Upgrade to Spring Boot 4.0 #18

Manually merged
ansv7779 merged 2 commits from spring-boot-4.0 into main 2026-05-22 20:34:38 +02:00
21 changed files with 142 additions and 103 deletions
Showing only changes of commit 9e21586c90 - Show all commits
+27 -7
View File
@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.11</version> <version>4.0.6</version>
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
@@ -19,7 +19,8 @@
<properties> <properties>
<java.version>17</java.version> <java.version>17</java.version>
<jte.version>3.1.12</jte.version> <jte.version>3.2.4</jte.version>
<spring-boot.version>4.0.6</spring-boot.version>
</properties> </properties>
<dependencies> <dependencies>
@@ -29,12 +30,12 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-webmvc</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>gg.jte</groupId> <groupId>gg.jte</groupId>
<artifactId>jte-spring-boot-starter-3</artifactId> <artifactId>jte-spring-boot-starter-4</artifactId>
<version>${jte.version}</version> <version>${jte.version}</version>
</dependency> </dependency>
<dependency> <dependency>
@@ -66,6 +67,11 @@
<artifactId>spring-boot-starter-tomcat</artifactId> <artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-web-server</artifactId>
<scope>provided</scope>
</dependency>
<!-- Testing --> <!-- Testing -->
<dependency> <dependency>
@@ -73,6 +79,15 @@
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-test</artifactId>
stne3960 marked this conversation as resolved
Review

Shouldn't this be <scope>test</scope>?

Shouldn't this be `<scope>test</scope>`?
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jackson-test</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-testcontainers</artifactId> <artifactId>spring-boot-testcontainers</artifactId>
@@ -85,12 +100,12 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.testcontainers</groupId> <groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId> <artifactId>testcontainers-junit-jupiter</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.testcontainers</groupId> <groupId>org.testcontainers</groupId>
<artifactId>mariadb</artifactId> <artifactId>testcontainers-mariadb</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
@@ -105,7 +120,7 @@
<path> <path>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId> <artifactId>spring-boot-configuration-processor</artifactId>
<version>3.3.0</version> <version>${spring-boot.version}</version>
</path> </path>
</annotationProcessorPaths> </annotationProcessorPaths>
</configuration> </configuration>
@@ -171,6 +186,11 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId> <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-flyway</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.flywaydb</groupId> <groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId> <artifactId>flyway-core</artifactId>
@@ -13,6 +13,7 @@ import org.springframework.security.config.Customizer;
import org.springframework.security.config.ObjectPostProcessor; import org.springframework.security.config.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority;
@@ -21,7 +22,6 @@ import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationProvider; import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationProvider;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationConsentAuthenticationProvider; import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationConsentAuthenticationProvider;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings; import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext; import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer; import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
@@ -95,7 +95,7 @@ public class AuthorizationServer extends SpringBootServletInitializer {
throws Exception throws Exception
{ {
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
OAuth2AuthorizationServerConfigurer.authorizationServer(); new OAuth2AuthorizationServerConfigurer();
String tokenEndpoint = authorizationServerSettings.getTokenEndpoint(); String tokenEndpoint = authorizationServerSettings.getTokenEndpoint();
RequestMatcher corsEnabledMatcher = new OrRequestMatcher( RequestMatcher corsEnabledMatcher = new OrRequestMatcher(
@@ -1,7 +1,7 @@
package se.su.dsv.oauth2.dev; package se.su.dsv.oauth2.dev;
import jakarta.servlet.http.HttpFilter; import jakarta.servlet.http.HttpFilter;
import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.security.autoconfigure.web.servlet.SecurityFilterProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@@ -12,9 +12,9 @@ import se.su.dsv.oauth2.Config;
@Profile("dev") @Profile("dev")
public class DevConfiguration { public class DevConfiguration {
@Bean @Bean
public FilterRegistrationBean<HttpFilter> fakeSSO(SecurityProperties securityProperties, Config config) { public FilterRegistrationBean<HttpFilter> fakeSSO(SecurityFilterProperties securityProperties, Config config) {
var filter = new FilterRegistrationBean<HttpFilter>(new FakeSSOFilter(config.developerEntitlement())); var filter = new FilterRegistrationBean<HttpFilter>(new FakeSSOFilter(config.developerEntitlement()));
filter.setOrder(securityProperties.getFilter().getOrder() - 1); filter.setOrder(securityProperties.getOrder() - 1);
return filter; return filter;
} }
} }
@@ -3,6 +3,7 @@ package se.su.dsv.oauth2.shibboleth;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.springframework.security.authentication.AuthenticationDetailsSource; import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.FactorGrantedAuthority;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
@@ -46,6 +47,8 @@ public class ShibbolethAuthenticationDetailsSource implements
authorities.add(entitlement); authorities.add(entitlement);
} }
} }
// The authentication performed by Shibboleth is password based.
authorities.add(FactorGrantedAuthority.fromAuthority(FactorGrantedAuthority.PASSWORD_AUTHORITY));
return authorities; return authorities;
} }
} }
@@ -7,7 +7,6 @@ import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpFilter; import jakarta.servlet.http.HttpFilter;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
@@ -34,10 +33,7 @@ import se.su.dsv.oauth2.shibboleth.ShibbolethAuthenticationDetails;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.util.*;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -100,7 +96,8 @@ public class CustomAuthorizationEndpointFilter extends HttpFilter {
authenticationConverter.convert(request); authenticationConverter.convert(request);
String authorizationUrl = getAuthorizationUrl(request); String authorizationUrl = getAuthorizationUrl(request);
JteModel view = templates.authorize(authorizationUrl, loggedInUser.getName(), (ShibbolethAuthenticationDetails) loggedInUser.getDetails()); Map<String, String[]> parameters = request.getParameterMap();
JteModel view = templates.authorize(authorizationUrl, parameters, loggedInUser.getName(), (ShibbolethAuthenticationDetails) loggedInUser.getDetails());
respondWithTemplate(response, view); respondWithTemplate(response, view);
} else if (Objects.equals(request.getMethod(), "POST")) { } else if (Objects.equals(request.getMethod(), "POST")) {
handleIncomingCustomAuthorizationRequest(request, response, loggedInUser); handleIncomingCustomAuthorizationRequest(request, response, loggedInUser);
@@ -119,14 +116,15 @@ public class CustomAuthorizationEndpointFilter extends HttpFilter {
principal.setDetails(buildShibbolethDetails(request)); principal.setDetails(buildShibbolethDetails(request));
Authentication authenticatedPrincipal = authenticationManager.authenticate(principal); Authentication authenticatedPrincipal = authenticationManager.authenticate(principal);
Authentication normalCodeRequest = authenticationConverter.convert(withGetMethod(request)); Authentication normalCodeRequest = authenticationConverter.convert(request);
OAuth2AuthorizationCodeRequestAuthenticationToken codeRequestAuthenticationToken = (OAuth2AuthorizationCodeRequestAuthenticationToken) normalCodeRequest; OAuth2AuthorizationCodeRequestAuthenticationToken codeRequestAuthenticationToken = (OAuth2AuthorizationCodeRequestAuthenticationToken) normalCodeRequest;
Authentication codeRequest = overridePrincipal(authenticatedPrincipal, codeRequestAuthenticationToken); Authentication codeRequest = overridePrincipal(authenticatedPrincipal, codeRequestAuthenticationToken);
Authentication authenticatedCodeRequest = authenticationManager.authenticate(codeRequest); Authentication authenticatedCodeRequest = authenticationManager.authenticate(codeRequest);
if (!authenticatedCodeRequest.isAuthenticated()) { if (!authenticatedCodeRequest.isAuthenticated()) {
String authorizationUrl = getAuthorizationUrl(request); String authorizationUrl = getAuthorizationUrl(request);
respondWithTemplate(response, templates.authorize(authorizationUrl, loggedInUser.getName(), (ShibbolethAuthenticationDetails) authenticatedPrincipal)); Map<String, String[]> parameters = request.getParameterMap();
respondWithTemplate(response, templates.authorize(authorizationUrl, parameters, loggedInUser.getName(), (ShibbolethAuthenticationDetails) authenticatedPrincipal));
} else { } else {
if (authenticatedCodeRequest instanceof OAuth2AuthorizationCodeRequestAuthenticationToken authenticatedCodeRequestAuthenticationToken) { if (authenticatedCodeRequest instanceof OAuth2AuthorizationCodeRequestAuthenticationToken authenticatedCodeRequestAuthenticationToken) {
sendAuthorizationResponse(request, response, authenticatedCodeRequestAuthenticationToken); sendAuthorizationResponse(request, response, authenticatedCodeRequestAuthenticationToken);
@@ -139,16 +137,7 @@ public class CustomAuthorizationEndpointFilter extends HttpFilter {
} }
private static String getAuthorizationUrl(final HttpServletRequest request) { private static String getAuthorizationUrl(final HttpServletRequest request) {
return request.getRequestURL().append('?').append(request.getQueryString()).toString(); return request.getRequestURL().toString();
}
private HttpServletRequest withGetMethod(final HttpServletRequest request) {
return new HttpServletRequestWrapper(request) {
@Override
public String getMethod() {
return "GET";
}
};
} }
private Authentication overridePrincipal( private Authentication overridePrincipal(
@@ -1,8 +1,10 @@
@import se.su.dsv.oauth2.shibboleth.Entitlement @import se.su.dsv.oauth2.shibboleth.Entitlement
@import se.su.dsv.oauth2.shibboleth.ShibbolethAuthenticationDetails @import se.su.dsv.oauth2.shibboleth.ShibbolethAuthenticationDetails
@import java.util.Map
@import java.util.stream.Collectors @import java.util.stream.Collectors
@param String authorizationUrl @param String authorizationUrl
@param Map<String, String[]> parameters
@param String principalName @param String principalName
@param ShibbolethAuthenticationDetails shibbolethDetails @param ShibbolethAuthenticationDetails shibbolethDetails
@@ -15,6 +17,11 @@
</p> </p>
<div class="d-flex justify-content-between flex-md-row flex-column mb-3"> <div class="d-flex justify-content-between flex-md-row flex-column mb-3">
<form action="${authorizationUrl}" method="post" class="flex-grow-1"> <form action="${authorizationUrl}" method="post" class="flex-grow-1">
@for (var entry : parameters.entrySet())
@for (var value : entry.getValue())
<input type="hidden" name="${entry.getKey()}" value="${value}">
@endfor
@endfor
<h2>Issue custom token</h2> <h2>Issue custom token</h2>
<div class="mb-3"> <div class="mb-3">
<label class="form-label" for="principal">Principal</label> <label class="form-label" for="principal">Principal</label>
@@ -51,6 +58,11 @@
<div class="vr mx-3 d-none d-md-block"></div> <div class="vr mx-3 d-none d-md-block"></div>
<hr class="d-md-none"> <hr class="d-md-none">
<form action="${authorizationUrl}" method="post" class="flex-grow-1"> <form action="${authorizationUrl}" method="post" class="flex-grow-1">
@for (var entry : parameters.entrySet())
@for (var value : entry.getValue())
<input type="hidden" name="${entry.getKey()}" value="${value}">
@endfor
@endfor
<h2>Continue as yourself</h2> <h2>Continue as yourself</h2>
<dl> <dl>
<dt>Principal</dt> <dt>Principal</dt>
@@ -1,11 +1,11 @@
package se.su.dsv.oauth2; package se.su.dsv.oauth2;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.mariadb.MariaDBContainer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@@ -24,25 +24,35 @@ import static se.su.dsv.oauth2.TestRegisteredClientConfiguration.REDIRECT_URI;
public abstract class AbstractMetadataCodeFlowTest extends AbstractMetadataTest { public abstract class AbstractMetadataCodeFlowTest extends AbstractMetadataTest {
@ServiceConnection @ServiceConnection
static MariaDBContainer<?> mariaDBContainer = new MariaDBContainer<>("mariadb:10.11"); static MariaDBContainer mariaDBContainer = new MariaDBContainer("mariadb:10.11");
protected TokenResponse authorize(Consumer<MockHttpServletRequestBuilder> consumer) throws Exception { protected TokenResponse authorize(Consumer<MockHttpServletRequestBuilder> consumer) throws Exception {
return getTokenResponse(get(getAuthorizationEndpoint()), consumer); return getTokenResponse(get(getAuthorizationEndpoint()), consumer, true);
} }
protected TokenResponse authorizePost(Consumer<MockHttpServletRequestBuilder> consumer) throws Exception { protected TokenResponse authorizePost(Consumer<MockHttpServletRequestBuilder> consumer) throws Exception {
return getTokenResponse(post(getAuthorizationEndpoint()), consumer); return getTokenResponse(post(getAuthorizationEndpoint()), consumer, false);
} }
private TokenResponse getTokenResponse( private TokenResponse getTokenResponse(
final MockHttpServletRequestBuilder builder, final MockHttpServletRequestBuilder builder,
final Consumer<MockHttpServletRequestBuilder> customizer) final Consumer<MockHttpServletRequestBuilder> customizer,
final boolean isGet)
throws Exception throws Exception
{ {
MockHttpServletRequestBuilder requestBuilder = builder MockHttpServletRequestBuilder requestBuilder;
.queryParam("response_type", "code") if (isGet) {
.queryParam("client_id", CLIENT_ID) requestBuilder = builder
.queryParam("redirect_uri", REDIRECT_URI); .queryParam("response_type", "code")
.queryParam("client_id", CLIENT_ID)
.queryParam("redirect_uri", REDIRECT_URI);
}
else {
requestBuilder = builder
.formField("response_type", "code")
.formField("client_id", CLIENT_ID)
.formField("redirect_uri", REDIRECT_URI);
}
customizer.accept(requestBuilder); customizer.accept(requestBuilder);
MvcResult authorizationResult = mockMvc.perform(requestBuilder) MvcResult authorizationResult = mockMvc.perform(requestBuilder)
@@ -1,7 +1,5 @@
package se.su.dsv.oauth2; package se.su.dsv.oauth2;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.jwk.source.JWKSource; import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.jwk.source.JWKSourceBuilder; import com.nimbusds.jose.jwk.source.JWKSourceBuilder;
@@ -12,10 +10,12 @@ import com.nimbusds.jwt.proc.ConfigurableJWTProcessor;
import com.nimbusds.jwt.proc.DefaultJWTProcessor; import com.nimbusds.jwt.proc.DefaultJWTProcessor;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.springframework.beans.factory.annotation.Autowired; 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.boot.test.context.SpringBootTest;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.json.JsonMapper;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
@@ -29,7 +29,7 @@ public class AbstractMetadataTest {
@Autowired @Autowired
protected MockMvc mockMvc; protected MockMvc mockMvc;
@Autowired @Autowired
protected ObjectMapper objectMapper; protected JsonMapper objectMapper;
private JsonNode metadata; private JsonNode metadata;
private ConfigurableJWTProcessor<SecurityContext> processor; private ConfigurableJWTProcessor<SecurityContext> processor;
@@ -45,7 +45,7 @@ public class AbstractMetadataTest {
metadata = objectMapper.readTree(responseBody); metadata = objectMapper.readTree(responseBody);
// 2. Get JWKS // 2. Get JWKS
URL jwksUri = URI.create(metadata.required("jwks_uri").asText()).toURL(); URL jwksUri = URI.create(metadata.required("jwks_uri").asString()).toURL();
JWKSource<SecurityContext> jwkSource = JWKSourceBuilder JWKSource<SecurityContext> jwkSource = JWKSourceBuilder
.create(jwksUri, new MockMvcResourceRetriever(mockMvc)) .create(jwksUri, new MockMvcResourceRetriever(mockMvc))
.build(); .build();
@@ -58,19 +58,19 @@ public class AbstractMetadataTest {
} }
protected String getAuthorizationEndpoint() { protected String getAuthorizationEndpoint() {
return metadata.get("authorization_endpoint").asText(); return metadata.get("authorization_endpoint").asString();
} }
protected String getTokenEndpoint() { protected String getTokenEndpoint() {
return metadata.get("token_endpoint").asText(); return metadata.get("token_endpoint").asString();
} }
protected String getIntrospectionEndpoint() { protected String getIntrospectionEndpoint() {
return metadata.get("introspection_endpoint").asText(); return metadata.get("introspection_endpoint").asString();
} }
protected String getUserInfoEndpoint() { protected String getUserInfoEndpoint() {
return metadata.get("userinfo_endpoint").asText(); return metadata.get("userinfo_endpoint").asString();
} }
protected JWTClaimsSet verifyToken(String token) throws Exception { protected JWTClaimsSet verifyToken(String token) throws Exception {
@@ -1,15 +1,15 @@
package se.su.dsv.oauth2; package se.su.dsv.oauth2;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; 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.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.mariadb.MariaDBContainer;
import tools.jackson.databind.JsonNode;
import tools.jackson.databind.json.JsonMapper;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -26,13 +26,13 @@ import static se.su.dsv.oauth2.TestRegisteredClientConfiguration.*;
public class AuthorizationCodeFlowTest { public class AuthorizationCodeFlowTest {
@ServiceConnection @ServiceConnection
static MariaDBContainer<?> mariaDBContainer = new MariaDBContainer<>("mariadb:10.11"); static MariaDBContainer mariaDBContainer = new MariaDBContainer("mariadb:10.11");
@Autowired @Autowired
MockMvc mockMvc; MockMvc mockMvc;
@Autowired @Autowired
ObjectMapper objectMapper; JsonMapper objectMapper;
@Test @Test
public void authorize_code_exchange_introspect() throws Exception { public void authorize_code_exchange_introspect() throws Exception {
@@ -72,7 +72,7 @@ public class AuthorizationCodeFlowTest {
String content = codeExchangeResult.getResponse().getContentAsString(); String content = codeExchangeResult.getResponse().getContentAsString();
JsonNode jsonNode = objectMapper.readTree(content); JsonNode jsonNode = objectMapper.readTree(content);
String accessToken = jsonNode.get("access_token").asText(); String accessToken = jsonNode.get("access_token").asString();
// 3. Introspect // 3. Introspect
mockMvc.perform(post("/oauth2/introspect") mockMvc.perform(post("/oauth2/introspect")
@@ -3,7 +3,7 @@ package se.su.dsv.oauth2;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.mariadb.MariaDBContainer;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -13,7 +13,7 @@ class AuthorizationServerTest {
@Container @Container
@ServiceConnection @ServiceConnection
static MariaDBContainer<?> mariaDBContainer = new MariaDBContainer<>("mariadb:10.11"); static MariaDBContainer mariaDBContainer = new MariaDBContainer("mariadb:10.11");
@Test @Test
void contextLoads() { void contextLoads() {
@@ -1,6 +1,5 @@
package se.su.dsv.oauth2; package se.su.dsv.oauth2;
import com.fasterxml.jackson.databind.JsonNode;
import com.nimbusds.jwt.JWTClaimsSet; import com.nimbusds.jwt.JWTClaimsSet;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@@ -9,7 +8,8 @@ import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.mariadb.MariaDBContainer;
import tools.jackson.databind.JsonNode;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@@ -32,7 +32,7 @@ public class ConsentFlowCustomAuthorizationTest extends AbstractMetadataTest {
public static final String DEVELOPER_ENTITLEMENT = "developer"; public static final String DEVELOPER_ENTITLEMENT = "developer";
@ServiceConnection @ServiceConnection
static MariaDBContainer<?> mariaDBContainer = new MariaDBContainer<>("mariadb:10.11"); static MariaDBContainer mariaDBContainer = new MariaDBContainer("mariadb:10.11");
@Test @Test
public void consent_is_disabled_for_developers() throws Exception { public void consent_is_disabled_for_developers() throws Exception {
@@ -42,8 +42,8 @@ public class ConsentFlowCustomAuthorizationTest extends AbstractMetadataTest {
MvcResult authorizationResult = mockMvc.perform(post(getAuthorizationEndpoint()) MvcResult authorizationResult = mockMvc.perform(post(getAuthorizationEndpoint())
.with(remoteUser(developerPrincipal) .with(remoteUser(developerPrincipal)
.entitlement(DEVELOPER_ENTITLEMENT)) .entitlement(DEVELOPER_ENTITLEMENT))
.queryParam("client_id", ConsentFlowTest.TestConfig.CLIENT_ID) .formField("client_id", ConsentFlowTest.TestConfig.CLIENT_ID)
.queryParam("response_type", "code") .formField("response_type", "code")
.formField("principal", customPrincipal)) .formField("principal", customPrincipal))
.andExpect(status().is3xxRedirection()) .andExpect(status().is3xxRedirection())
.andExpect(redirectedUrlPattern(ConsentFlowTest.TestConfig.REDIRECT_URI + "?*")) .andExpect(redirectedUrlPattern(ConsentFlowTest.TestConfig.REDIRECT_URI + "?*"))
@@ -66,7 +66,7 @@ public class ConsentFlowCustomAuthorizationTest extends AbstractMetadataTest {
.andReturn(); .andReturn();
JsonNode tokenResponse = objectMapper.readTree(tokenResult.getResponse().getContentAsString()); JsonNode tokenResponse = objectMapper.readTree(tokenResult.getResponse().getContentAsString());
JWTClaimsSet claims = verifyToken(tokenResponse.required("access_token").asText()); JWTClaimsSet claims = verifyToken(tokenResponse.required("access_token").asString());
assertEquals(customPrincipal, claims.getSubject()); assertEquals(customPrincipal, claims.getSubject());
} }
@@ -15,7 +15,7 @@ import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.ResultActions;
import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.mariadb.MariaDBContainer;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@@ -35,7 +35,7 @@ import static se.su.dsv.oauth2.ShibbolethRequestProcessor.remoteUser;
public class ConsentFlowTest extends AbstractMetadataTest { public class ConsentFlowTest extends AbstractMetadataTest {
@ServiceConnection @ServiceConnection
static MariaDBContainer<?> mariaDBContainer = new MariaDBContainer<>("mariadb:10.11"); static MariaDBContainer mariaDBContainer = new MariaDBContainer("mariadb:10.11");
@Test @Test
public void asks_end_user_for_consent() throws Exception { public void asks_end_user_for_consent() throws Exception {
@@ -195,6 +195,7 @@ public class ConsentFlowTest extends AbstractMetadataTest {
.scope(OidcScopes.EMAIL) .scope(OidcScopes.EMAIL)
.clientSettings(ClientSettings.builder() .clientSettings(ClientSettings.builder()
.requireAuthorizationConsent(true) .requireAuthorizationConsent(true)
.requireProofKey(false)
.build()) .build())
.build(); .build();
@@ -104,13 +104,13 @@ public class EmbeddedContainerTest {
final MultiValueMap<String, Object> form = new LinkedMultiValueMap<>(); final MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
form.put("principal", List.of("test")); form.put("principal", List.of("test"));
form.put("response_type", List.of("code"));
form.put("client_id", List.of(CLIENT_ID));
form.put("redirect_uri", List.of(CLIENT_REDIRECT_URI));
form.put("scope", List.of("openid profile email"));
String authorizationEndpoint = parsedMetadata.required("authorization_endpoint").asText(); String authorizationEndpoint = parsedMetadata.required("authorization_endpoint").asText();
String authorizeUri = UriComponentsBuilder.fromUriString(authorizationEndpoint) String authorizeUri = UriComponentsBuilder.fromUriString(authorizationEndpoint)
.queryParam("response_type", "code")
.queryParam("client_id", CLIENT_ID)
.queryParam("redirect_uri", CLIENT_REDIRECT_URI)
.queryParam("scope", "openid profile email")
.build() .build()
.toUriString(); .toUriString();
@@ -3,11 +3,11 @@ package se.su.dsv.oauth2;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; 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.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.mariadb.MariaDBContainer;
import se.su.dsv.oauth2.admin.ClientData; import se.su.dsv.oauth2.admin.ClientData;
import se.su.dsv.oauth2.admin.ClientManagementService; import se.su.dsv.oauth2.admin.ClientManagementService;
import se.su.dsv.oauth2.admin.NewClient; import se.su.dsv.oauth2.admin.NewClient;
@@ -34,7 +34,7 @@ public class PublicClientCodeFlowTest extends AbstractMetadataCodeFlowTest {
private static final String REDIRECT_URI = "http://localhost/public"; private static final String REDIRECT_URI = "http://localhost/public";
@ServiceConnection @ServiceConnection
static MariaDBContainer<?> mariaDBContainer = new MariaDBContainer<>("mariadb:10.11"); static MariaDBContainer mariaDBContainer = new MariaDBContainer("mariadb:10.11");
@Autowired @Autowired
private ClientManagementService clientManagementService; private ClientManagementService clientManagementService;
@@ -2,8 +2,8 @@ package se.su.dsv.oauth2;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; 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.boot.test.context.SpringBootTest;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import se.su.dsv.oauth2.admin.ClientData; import se.su.dsv.oauth2.admin.ClientData;
@@ -1,7 +1,7 @@
package se.su.dsv.oauth2; package se.su.dsv.oauth2;
import org.apache.catalina.realm.GenericPrincipal; import org.apache.catalina.realm.GenericPrincipal;
import org.springframework.lang.NonNull; import org.jspecify.annotations.NonNull;
import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.web.servlet.request.RequestPostProcessor; import org.springframework.test.web.servlet.request.RequestPostProcessor;
@@ -64,7 +64,7 @@ public class StagingProfileTest extends AbstractMetadataCodeFlowTest {
TokenResponse tokenResponse = authorizePost(request -> request TokenResponse tokenResponse = authorizePost(request -> request
.with(remoteUser(principal) .with(remoteUser(principal)
.entitlement(DEVELOPER_ENTITLEMENT)) .entitlement(DEVELOPER_ENTITLEMENT))
.queryParam("scope", "openid profile") .formField("scope", "openid profile")
.formField("principal", principal) .formField("principal", principal)
.formField("displayName", customDisplayName)); .formField("displayName", customDisplayName));
@@ -85,7 +85,7 @@ public class StagingProfileTest extends AbstractMetadataCodeFlowTest {
TokenResponse tokenResponse = authorizePost(request -> request TokenResponse tokenResponse = authorizePost(request -> request
.with(remoteUser(principal) .with(remoteUser(principal)
.entitlement(DEVELOPER_ENTITLEMENT)) .entitlement(DEVELOPER_ENTITLEMENT))
.queryParam("scope", "openid email") .formField("scope", "openid email")
.formField("principal", principal) .formField("principal", principal)
.formField("mail", customMail)); .formField("mail", customMail));
@@ -106,7 +106,7 @@ public class StagingProfileTest extends AbstractMetadataCodeFlowTest {
TokenResponse tokenResponse = authorizePost(request -> request TokenResponse tokenResponse = authorizePost(request -> request
.with(remoteUser(principal) .with(remoteUser(principal)
.entitlement(DEVELOPER_ENTITLEMENT)) .entitlement(DEVELOPER_ENTITLEMENT))
.queryParam("scope", "openid profile") .formField("scope", "openid profile")
.formField("principal", principal) .formField("principal", principal)
.formField("givenName", customGivenName)); .formField("givenName", customGivenName));
@@ -127,7 +127,7 @@ public class StagingProfileTest extends AbstractMetadataCodeFlowTest {
TokenResponse tokenResponse = authorizePost(request -> request TokenResponse tokenResponse = authorizePost(request -> request
.with(remoteUser(principal) .with(remoteUser(principal)
.entitlement(DEVELOPER_ENTITLEMENT)) .entitlement(DEVELOPER_ENTITLEMENT))
.queryParam("scope", "openid profile") .formField("scope", "openid profile")
.formField("principal", principal) .formField("principal", principal)
.formField("sn", customFamilyName)); .formField("sn", customFamilyName));
@@ -148,7 +148,7 @@ public class StagingProfileTest extends AbstractMetadataCodeFlowTest {
TokenResponse tokenResponse = authorizePost(request -> request TokenResponse tokenResponse = authorizePost(request -> request
.with(remoteUser(principal) .with(remoteUser(principal)
.entitlement(DEVELOPER_ENTITLEMENT)) .entitlement(DEVELOPER_ENTITLEMENT))
.queryParam("scope", "openid profile") .formField("scope", "openid profile")
.formField("principal", principal) .formField("principal", principal)
.formField("entitlements", customEntitlement)); .formField("entitlements", customEntitlement));
@@ -168,8 +168,8 @@ public class StagingProfileTest extends AbstractMetadataCodeFlowTest {
mockMvc.perform(post(getAuthorizationEndpoint()) mockMvc.perform(post(getAuthorizationEndpoint())
.with(remoteUser("developer") .with(remoteUser("developer")
.entitlement(DEVELOPER_ENTITLEMENT)) .entitlement(DEVELOPER_ENTITLEMENT))
.queryParam("client_id", CLIENT_ID) .formField("client_id", CLIENT_ID)
.queryParam("redirect_uri", REDIRECT_URI) .formField("redirect_uri", REDIRECT_URI)
.formField("principal", "developer")) .formField("principal", "developer"))
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(status().reason(containsString("response_type"))); .andExpect(status().reason(containsString("response_type")));
@@ -180,10 +180,10 @@ public class StagingProfileTest extends AbstractMetadataCodeFlowTest {
mockMvc.perform(post(getAuthorizationEndpoint()) mockMvc.perform(post(getAuthorizationEndpoint())
.with(remoteUser("developer") .with(remoteUser("developer")
.entitlement(DEVELOPER_ENTITLEMENT)) .entitlement(DEVELOPER_ENTITLEMENT))
.queryParam("response_type", "code") .formField("response_type", "code")
.queryParam("client_id", CLIENT_ID) .formField("client_id", CLIENT_ID)
.queryParam("redirect_uri", REDIRECT_URI) .formField("redirect_uri", REDIRECT_URI)
.queryParam("scope", "invalid") .formField("scope", "invalid")
.formField("principal", "developer")) .formField("principal", "developer"))
.andExpect(status().is3xxRedirection()) .andExpect(status().is3xxRedirection())
.andExpect(result -> { .andExpect(result -> {
@@ -197,9 +197,9 @@ public class StagingProfileTest extends AbstractMetadataCodeFlowTest {
mockMvc.perform(post(getAuthorizationEndpoint()) mockMvc.perform(post(getAuthorizationEndpoint())
.with(remoteUser("developer") .with(remoteUser("developer")
.entitlement(DEVELOPER_ENTITLEMENT)) .entitlement(DEVELOPER_ENTITLEMENT))
.queryParam("response_type", "code") .formField("response_type", "code")
.queryParam("client_id", "invalid-client-id") .formField("client_id", "invalid-client-id")
.queryParam("redirect_uri", REDIRECT_URI) .formField("redirect_uri", REDIRECT_URI)
.formField("principal", "developer")) .formField("principal", "developer"))
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(status().reason(containsString("client_id"))); .andExpect(status().reason(containsString("client_id")));
@@ -212,11 +212,11 @@ public class StagingProfileTest extends AbstractMetadataCodeFlowTest {
mockMvc.perform(post(getAuthorizationEndpoint()) mockMvc.perform(post(getAuthorizationEndpoint())
.with(remoteUser("developer") .with(remoteUser("developer")
.entitlement(DEVELOPER_ENTITLEMENT)) .entitlement(DEVELOPER_ENTITLEMENT))
.queryParam("response_type", "code") .formField("response_type", "code")
.queryParam("client_id", CLIENT_ID) .formField("client_id", CLIENT_ID)
.queryParam("redirect_uri", REDIRECT_URI) .formField("redirect_uri", REDIRECT_URI)
.queryParam("state", state) .formField("state", state)
.queryParam("scope", "invalid") .formField("scope", "invalid")
.formField("principal", "developer")) .formField("principal", "developer"))
.andExpect(status().is3xxRedirection()) .andExpect(status().is3xxRedirection())
.andExpect(result -> { .andExpect(result -> {
@@ -8,6 +8,7 @@ import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.oidc.OidcScopes; import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository; import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
@TestConfiguration @TestConfiguration
public class TestRegisteredClientConfiguration { public class TestRegisteredClientConfiguration {
@@ -21,6 +22,9 @@ public class TestRegisteredClientConfiguration {
InMemoryRegisteredClientRepository testRegisteredClientRepository() { InMemoryRegisteredClientRepository testRegisteredClientRepository() {
RegisteredClient registeredClient = RegisteredClient.withId("id") RegisteredClient registeredClient = RegisteredClient.withId("id")
.clientId(CLIENT_ID) .clientId(CLIENT_ID)
.clientSettings(ClientSettings.builder()
.requireProofKey(false)
.build())
.clientSecret("{noop}" + CLIENT_SECRET) .clientSecret("{noop}" + CLIENT_SECRET)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri(REDIRECT_URI) .redirectUri(REDIRECT_URI)
@@ -1,10 +1,10 @@
package se.su.dsv.oauth2; package se.su.dsv.oauth2;
import com.fasterxml.jackson.databind.JsonNode;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.oauth2.core.oidc.OidcScopes; import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import tools.jackson.databind.JsonNode;
import java.net.URI; import java.net.URI;
@@ -26,7 +26,7 @@ public class UserInfoEndpointTest extends AbstractMetadataCodeFlowTest {
JsonNode openidConfiguration = objectMapper.readTree(mvcResult.getResponse().getContentAsString()); JsonNode openidConfiguration = objectMapper.readTree(mvcResult.getResponse().getContentAsString());
String userinfoEndpoint = openidConfiguration.required("userinfo_endpoint").asText(); String userinfoEndpoint = openidConfiguration.required("userinfo_endpoint").asString();
URI userInfoUri = URI.create(userinfoEndpoint); URI userInfoUri = URI.create(userinfoEndpoint);
assertEquals("/oidc/userinfo", userInfoUri.getPath()); assertEquals("/oidc/userinfo", userInfoUri.getPath());
@@ -2,11 +2,11 @@ package se.su.dsv.oauth2.web;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; 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.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.mariadb.MariaDBContainer;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
@@ -20,7 +20,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
class AdminControllerTest { class AdminControllerTest {
@Container @Container
@ServiceConnection @ServiceConnection
static MariaDBContainer<?> mariaDBContainer = new MariaDBContainer<>("mariadb:10.11"); static MariaDBContainer mariaDBContainer = new MariaDBContainer("mariadb:10.11");
@Autowired @Autowired
MockMvc mockMvc; MockMvc mockMvc;
@@ -28,7 +28,7 @@ class AdminControllerTest {
@Test @Test
void is_protected() throws Exception { void is_protected() throws Exception {
mockMvc.perform(get("/admin")) mockMvc.perform(get("/admin"))
.andExpect(redirectedUrl("http://localhost/login")); .andExpect(redirectedUrl("/login"));
} }
@Test @Test
@@ -2,14 +2,14 @@ package se.su.dsv.oauth2.web.client;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; 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.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
import org.springframework.test.annotation.Rollback; import org.springframework.test.annotation.Rollback;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.mariadb.MariaDBContainer;
import se.su.dsv.oauth2.admin.Client; import se.su.dsv.oauth2.admin.Client;
import se.su.dsv.oauth2.admin.ClientManagementService; import se.su.dsv.oauth2.admin.ClientManagementService;
@@ -35,7 +35,7 @@ public class ClientAdminControllerTest {
public static final String DEVELOPER_ENTITLEMENT = "developer"; public static final String DEVELOPER_ENTITLEMENT = "developer";
@ServiceConnection @ServiceConnection
static MariaDBContainer<?> mariaDBContainer = new MariaDBContainer<>("mariadb:10.11"); static MariaDBContainer mariaDBContainer = new MariaDBContainer("mariadb:10.11");
@Autowired @Autowired
MockMvc mockMvc; MockMvc mockMvc;