Skip to content

Commit 6baeccf

Browse files
committed
ResourceServerConfigurer on Auth0 Sample
Reconfigured the auth0 sample to use the Resource Server Configurer. Note that this uncovered a problem with BearerTokenErrorHandler where is was calling sendError instead of setStatus. The contract of sendError indicates that it converts the content type to text/html and allows the container to send an html error response with the given message. Calling setStatus seems more apppropriate in our case. Issue: spring-projects/spring-security#5125
1 parent c6039e9 commit 6baeccf

File tree

6 files changed

+38
-65
lines changed

6 files changed

+38
-65
lines changed

oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/resourceserver/BearerTokenErrorHandler.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ protected void handle(
8787
.collect(Collectors.joining(", ", " ", ""));
8888
}
8989
response.addHeader(HttpHeaders.WWW_AUTHENTICATE, wwwAuthenticate);
90-
response.sendError(httpStatus.value(), httpStatus.getReasonPhrase());
90+
response.setStatus(httpStatus.value());
9191
}
9292

9393
public void setRealmName(String realmName) {
+2-2
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@
3434
/**
3535
* @author Josh Cummings
3636
*/
37-
public class Auth0JwtDecoderJwkSupport implements JwtDecoder {
37+
public class Auth0JwtDecoder implements JwtDecoder {
3838
private JWTVerifier verifier;
3939

40-
public Auth0JwtDecoderJwkSupport(JWTVerifier verifier) {
40+
public Auth0JwtDecoder(JWTVerifier verifier) {
4141
this.verifier = verifier;
4242
}
4343

samples/boot/oauth2/resource-server/auth0/src/main/java/sample/MessageController.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public Message findOne(@PathVariable Long id) {
4343

4444
@PostMapping
4545
public Message save(@Valid @RequestBody Message message) {
46-
return this.messages.save(message);
46+
Message n = this.messages.save(message);
47+
return n;
4748
}
4849
}

samples/boot/oauth2/resource-server/auth0/src/main/java/sample/MessagesApplication.java

+23-57
Original file line numberDiff line numberDiff line change
@@ -19,90 +19,56 @@
1919
import com.auth0.jwt.JWTVerifier;
2020
import com.auth0.jwt.algorithms.Algorithm;
2121
import com.auth0.jwt.interfaces.RSAKeyProvider;
22+
import org.springframework.beans.BeansException;
23+
import org.springframework.beans.factory.BeanFactory;
24+
import org.springframework.beans.factory.BeanFactoryAware;
25+
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
2226
import org.springframework.boot.SpringApplication;
2327
import org.springframework.boot.autoconfigure.SpringBootApplication;
2428
import org.springframework.context.annotation.Bean;
25-
import org.springframework.http.HttpStatus;
26-
import org.springframework.security.authentication.AuthenticationManager;
27-
import org.springframework.security.authentication.AuthenticationProvider;
28-
import org.springframework.security.authentication.ProviderManager;
2929
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
3030
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
3131
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
32+
import org.springframework.security.config.annotation.web.configurers.oauth2.resourceserver.ResourceServerConfigurer;
3233
import org.springframework.security.oauth2.jwt.JwtDecoder;
33-
import org.springframework.security.oauth2.resourceserver.access.expression.OAuth2ResourceServerExpressions;
34-
import org.springframework.security.oauth2.resourceserver.access.expression.OAuth2Expressions;
35-
import org.springframework.security.oauth2.resourceserver.authentication.JwtAccessTokenAuthenticationProvider;
36-
import org.springframework.security.oauth2.resourceserver.authentication.JwtAccessTokenVerifier;
37-
import org.springframework.security.oauth2.resourceserver.web.BearerTokenAuthenticationFilter;
38-
import org.springframework.security.web.AuthenticationEntryPoint;
39-
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
40-
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
4134

4235
import java.io.InputStream;
43-
import java.util.Arrays;
4436

4537
@SpringBootApplication
46-
public class MessagesApplication {
38+
public class MessagesApplication implements BeanFactoryAware {
39+
40+
private ConfigurableBeanFactory beanFactory;
41+
42+
@Override
43+
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
44+
if ( beanFactory instanceof ConfigurableBeanFactory ) {
45+
this.beanFactory = (ConfigurableBeanFactory) beanFactory;
46+
}
47+
}
4748

4849
@EnableGlobalMethodSecurity(prePostEnabled = true)
4950
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
5051
@Override
5152
protected void configure(HttpSecurity http) throws Exception {
52-
http
53-
.addFilterAfter(
54-
oauthResourceAuthenticationFilter(),
55-
BasicAuthenticationFilter.class)
56-
.exceptionHandling()
57-
.authenticationEntryPoint(restAuthenticationEntryPoint()).and()
58-
.authorizeRequests()
59-
.anyRequest().authenticated().and()
60-
.csrf().disable();
61-
}
62-
}
63-
64-
65-
66-
@Bean
67-
public OAuth2Expressions oauth2() {
68-
return new OAuth2ResourceServerExpressions();
69-
}
7053

71-
// @Bean -- We don't want this to get wired by Spring Boot as a servlet-level filter
72-
// Is there a more clever way to do this?
73-
BearerTokenAuthenticationFilter oauthResourceAuthenticationFilter() {
74-
BearerTokenAuthenticationFilter filter =
75-
new BearerTokenAuthenticationFilter(authenticationManager());
54+
resourceServer()
55+
.jwt(jwtDecoder())
7656

77-
return filter;
78-
}
79-
80-
@Bean
81-
AuthenticationManager authenticationManager() {
82-
return new ProviderManager(
83-
Arrays.asList(oauthResourceAuthenticationProvider())
84-
);
85-
}
57+
.and().apply(http);
58+
}
8659

87-
@Bean
88-
AuthenticationProvider oauthResourceAuthenticationProvider() {
89-
JwtAccessTokenAuthenticationProvider provider =
90-
new JwtAccessTokenAuthenticationProvider(jwtDecoder(), new JwtAccessTokenVerifier());
60+
protected ResourceServerConfigurer resourceServer() {
61+
return new ResourceServerConfigurer(MessagesApplication.this.beanFactory);
62+
}
9163

92-
return provider;
9364
}
9465

9566
@Bean
9667
JwtDecoder jwtDecoder() {
9768
InputStream is = this.getClass().getClassLoader().getResourceAsStream("id_rsa.pub");
9869
RSAKeyProvider provider = new PemParsingPublicKeyOnlyRSAKeyProvider(is);
9970
JWTVerifier verifier = JWT.require(Algorithm.RSA256(provider)).withIssuer("rob").build();
100-
return new Auth0JwtDecoderJwkSupport(verifier);
101-
}
102-
103-
@Bean
104-
AuthenticationEntryPoint restAuthenticationEntryPoint() {
105-
return new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED);
71+
return new Auth0JwtDecoder(verifier);
10672
}
10773

10874
public static void main(String[] args) {
+3-3
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import static org.assertj.core.api.Assertions.assertThat;
3030
import static org.assertj.core.api.Assertions.assertThatThrownBy;
3131

32-
public class Auth0JwtDecoderJwkSupportTests {
32+
public class Auth0JwtDecoderTests {
3333
@Test
3434
public void whenSignatureAndIssuerValid_thenDecodeToken() throws IOException {
3535
String goodToken = "eyJraWQiOiIxMjMiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzY29wZSI6Im1lc3NhZ2UucmVhZCIsImlzcyI6InJvYiIsImV4cCI6MjE0NzQwNzIwMCwiaWF0IjoxNTE2MjU1MjAwfQ.XJ8d6fQpo53eH_8nduS7rZOB9szHkVTYkZgzfpF3s6dq0DH-ovgFWBE1evfIXHTQwpAil1X856lp_mvJH0pWVXjM2jM5g_qMGen25210-9R9A94ShiM3iSeMAozHl2L6nmdifJR9Na0fWPo4rogB6_N0GoBG2haaB9yU2r925hw";
@@ -63,7 +63,7 @@ public void whenExpired_thenTokenExpiredException() throws IOException {
6363
.isInstanceOf(JwtException.class);
6464
}
6565

66-
protected Auth0JwtDecoderJwkSupport defaultVerifier() throws IOException {
66+
protected Auth0JwtDecoder defaultVerifier() throws IOException {
6767
InputStream is = this.getClass()
6868
.getClassLoader().getResourceAsStream("id_rsa.pub");
6969

@@ -72,6 +72,6 @@ protected Auth0JwtDecoderJwkSupport defaultVerifier() throws IOException {
7272

7373
JWTVerifier verifier = JWT.require(Algorithm.RSA256(key)).withIssuer("rob").build();
7474

75-
return new Auth0JwtDecoderJwkSupport(verifier);
75+
return new Auth0JwtDecoder(verifier);
7676
}
7777
}

samples/boot/oauth2/resource-server/auth0/src/test/java/sample/MessagesApplicationTests.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.junit.Test;
2121
import org.junit.runner.RunWith;
2222
import org.springframework.beans.factory.annotation.Autowired;
23+
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
2324
import org.springframework.boot.test.context.SpringBootTest;
2425
import org.springframework.boot.test.web.client.TestRestTemplate;
2526
import org.springframework.http.HttpEntity;
@@ -28,13 +29,18 @@
2829
import org.springframework.http.HttpStatus;
2930
import org.springframework.http.ResponseEntity;
3031
import org.springframework.test.context.junit4.SpringRunner;
32+
import org.springframework.test.web.servlet.MockMvc;
3133

3234
import static org.assertj.core.api.Assertions.assertThat;
3335

3436
@RunWith(SpringRunner.class)
3537
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
38+
@AutoConfigureMockMvc
3639
public class MessagesApplicationTests {
3740

41+
@Autowired
42+
MockMvc mvc;
43+
3844
@Autowired
3945
TestRestTemplate rest;
4046

@@ -58,7 +64,7 @@ public void setUp() throws Exception {
5864
}
5965

6066
@Test
61-
public void whenProperAuthorizationHeader_thenAllowBoth() {
67+
public void whenProperAuthorizationHeader_thenAllowBoth() throws Exception {
6268
Message toSave = new Message("New");
6369

6470
ResponseEntity<Message> response = postForMessage("/messages", this.messageBothAuthority, toSave);

0 commit comments

Comments
 (0)