Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,25 @@

package org.springframework.boot.autoconfigure.security.oauth2.server.servlet;

import java.util.Set;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.security.ConditionalOnDefaultWebSecurity;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
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.web.SecurityFilterChain;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;

import static org.springframework.security.config.Customizer.withDefaults;

Expand All @@ -49,8 +54,8 @@ SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) th
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class).oidc(withDefaults());
http.oauth2ResourceServer((resourceServer) -> resourceServer.jwt(withDefaults()));
http.exceptionHandling(
(exceptions) -> exceptions.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")));
http.exceptionHandling((exceptions) -> exceptions.defaultAuthenticationEntryPointFor(
new LoginUrlAuthenticationEntryPoint("/login"), createRequestMatcher()));
return http.build();
}

Expand All @@ -61,4 +66,10 @@ SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Excepti
return http.build();
}

private static RequestMatcher createRequestMatcher() {
MediaTypeRequestMatcher requestMatcher = new MediaTypeRequestMatcher(MediaType.TEXT_HTML);
requestMatcher.setIgnoredMediaTypes(Set.of(MediaType.ALL));
return requestMatcher;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package smoketest.oauth2.server;

import java.net.URI;
import java.util.List;
import java.util.Map;
import java.util.Objects;

Expand All @@ -31,6 +32,7 @@
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
Expand Down Expand Up @@ -118,4 +120,49 @@ void validTokenRequestShouldReturnTokenResponse() {
.isEqualTo(OAuth2AccessToken.TokenType.BEARER.getValue());
}

@Test
void anonymousTokenRequestShouldReturnUnauthorized() {
HttpHeaders headers = new HttpHeaders();
HttpEntity<Object> request = new HttpEntity<>(headers);
String requestUri = UriComponentsBuilder.fromUriString("/token")
.queryParam(OAuth2ParameterNames.CLIENT_ID, "messaging-client")
.queryParam(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.queryParam(OAuth2ParameterNames.SCOPE, "message.read+message.write")
.toUriString();
ResponseEntity<Map<String, Object>> entity = this.restTemplate.exchange(requestUri, HttpMethod.POST, request,
MAP_TYPE_REFERENCE);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
}

@Test
void anonymousTokenRequestWithAcceptHeaderAllShouldReturnUnauthorized() {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(List.of(MediaType.ALL));
HttpEntity<Object> request = new HttpEntity<>(headers);
String requestUri = UriComponentsBuilder.fromUriString("/token")
.queryParam(OAuth2ParameterNames.CLIENT_ID, "messaging-client")
.queryParam(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.queryParam(OAuth2ParameterNames.SCOPE, "message.read+message.write")
.toUriString();
ResponseEntity<Map<String, Object>> entity = this.restTemplate.exchange(requestUri, HttpMethod.POST, request,
MAP_TYPE_REFERENCE);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
}

@Test
void anonymousTokenRequestWithAcceptHeaderTextHtmlShouldRedirectToLogin() {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(List.of(MediaType.TEXT_HTML));
HttpEntity<Object> request = new HttpEntity<>(headers);
String requestUri = UriComponentsBuilder.fromUriString("/token")
.queryParam(OAuth2ParameterNames.CLIENT_ID, "messaging-client")
.queryParam(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.CLIENT_CREDENTIALS.getValue())
.queryParam(OAuth2ParameterNames.SCOPE, "message.read+message.write")
.toUriString();
ResponseEntity<Map<String, Object>> entity = this.restTemplate.exchange(requestUri, HttpMethod.POST, request,
MAP_TYPE_REFERENCE);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FOUND);
assertThat(entity.getHeaders().getLocation()).isEqualTo(URI.create("http://localhost:" + this.port + "/login"));
}

}