diff --git a/samples/boot/hellorsocket/spring-security-samples-boot-hellorsocket.gradle b/samples/boot/hellorsocket/spring-security-samples-boot-hellorsocket.gradle deleted file mode 100644 index f2b788a0e2..0000000000 --- a/samples/boot/hellorsocket/spring-security-samples-boot-hellorsocket.gradle +++ /dev/null @@ -1,11 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-core') - compile project(':spring-security-config') - compile project(':spring-security-rsocket') - compile 'org.springframework.boot:spring-boot-starter-rsocket' - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/hellorsocket/src/integration-test/java/sample/HelloRSocketApplicationITests.java b/samples/boot/hellorsocket/src/integration-test/java/sample/HelloRSocketApplicationITests.java deleted file mode 100644 index 0709dd93bc..0000000000 --- a/samples/boot/hellorsocket/src/integration-test/java/sample/HelloRSocketApplicationITests.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.rsocket.context.LocalRSocketServerPort; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.messaging.rsocket.RSocketRequester; -import org.springframework.security.rsocket.metadata.BasicAuthenticationEncoder; -import org.springframework.security.rsocket.metadata.UsernamePasswordMetadata; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -import org.junit.Test; -import org.junit.runner.RunWith; -import reactor.core.publisher.Mono; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.springframework.security.rsocket.metadata.UsernamePasswordMetadata.BASIC_AUTHENTICATION_MIME_TYPE; - -/** - * @author Rob Winch - * @author EddĂș MelĂ©ndez - * @since 5.0 - */ -@RunWith(SpringRunner.class) -@TestPropertySource(properties = "spring.rsocket.server.port=0") -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class HelloRSocketApplicationITests { - - @Autowired - RSocketRequester.Builder requester; - - @LocalRSocketServerPort - int port; - - @Test - public void messageWhenAuthenticatedThenSuccess() { - UsernamePasswordMetadata credentials = new UsernamePasswordMetadata("user", "password"); - RSocketRequester requester = this.requester - .rsocketStrategies((builder) -> builder.encoder(new BasicAuthenticationEncoder())) - .setupMetadata(credentials, BASIC_AUTHENTICATION_MIME_TYPE) - .connectTcp("localhost", this.port) - .block(); - - String message = requester.route("message") - .data(Mono.empty()) - .retrieveMono(String.class) - .block(); - - assertThat(message).isEqualTo("Hello"); - } - - @Test - public void messageWhenNotAuthenticatedThenError() { - RSocketRequester requester = this.requester - .connectTcp("localhost", this.port) - .block(); - - assertThatThrownBy(() -> requester.route("message") - .data(Mono.empty()) - .retrieveMono(String.class) - .block()) - .isNotNull(); - } - -} diff --git a/samples/boot/hellorsocket/src/main/java/sample/HelloRSocketApplication.java b/samples/boot/hellorsocket/src/main/java/sample/HelloRSocketApplication.java deleted file mode 100644 index fbbc6df27d..0000000000 --- a/samples/boot/hellorsocket/src/main/java/sample/HelloRSocketApplication.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Rob Winch - * @since 5.2 - */ -@SpringBootApplication -public class HelloRSocketApplication { - - public static void main(String[] args) { - SpringApplication.run(HelloRSocketApplication.class, args); - } - -} diff --git a/samples/boot/hellorsocket/src/main/java/sample/HelloRSocketSecurityConfig.java b/samples/boot/hellorsocket/src/main/java/sample/HelloRSocketSecurityConfig.java deleted file mode 100644 index 9f469f08e7..0000000000 --- a/samples/boot/hellorsocket/src/main/java/sample/HelloRSocketSecurityConfig.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.rsocket.EnableRSocketSecurity; -import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; - -/** - * @author Rob Winch - * @since 5.2 - */ -@Configuration -@EnableRSocketSecurity -public class HelloRSocketSecurityConfig { - - @Bean - MapReactiveUserDetailsService userDetailsService() { - UserDetails user = User.withDefaultPasswordEncoder() - .username("user") - .password("password") - .roles("SETUP") - .build(); - return new MapReactiveUserDetailsService(user); - } - -} diff --git a/samples/boot/hellorsocket/src/main/java/sample/MessageController.java b/samples/boot/hellorsocket/src/main/java/sample/MessageController.java deleted file mode 100644 index 0150b3f821..0000000000 --- a/samples/boot/hellorsocket/src/main/java/sample/MessageController.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.stereotype.Controller; -import reactor.core.publisher.Mono; - -/** - * @author Rob Winch - * @since 5.2 - */ -@Controller -public class MessageController { - - @MessageMapping("message") - public Mono message() { - return Mono.just("Hello"); - } -} diff --git a/samples/boot/hellorsocket/src/main/resources/application.properties b/samples/boot/hellorsocket/src/main/resources/application.properties deleted file mode 100644 index 0d91b628f6..0000000000 --- a/samples/boot/hellorsocket/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.rsocket.server.port=8080 diff --git a/samples/boot/hellowebflux-method/spring-security-samples-boot-hellowebflux-method.gradle b/samples/boot/hellowebflux-method/spring-security-samples-boot-hellowebflux-method.gradle deleted file mode 100644 index c21781806f..0000000000 --- a/samples/boot/hellowebflux-method/spring-security-samples-boot-hellowebflux-method.gradle +++ /dev/null @@ -1,12 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-core') - compile project(':spring-security-config') - compile project(':spring-security-web') - compile 'org.springframework.boot:spring-boot-starter-webflux' - - testCompile project(':spring-security-test') - testCompile 'io.projectreactor:reactor-test' - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/hellowebflux-method/src/integration-test/java/sample/HelloWebfluxMethodApplicationITests.java b/samples/boot/hellowebflux-method/src/integration-test/java/sample/HelloWebfluxMethodApplicationITests.java deleted file mode 100644 index d95956b2d6..0000000000 --- a/samples/boot/hellowebflux-method/src/integration-test/java/sample/HelloWebfluxMethodApplicationITests.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import java.util.function.Consumer; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * @author Rob Winch - * @since 5.0 - */ -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class HelloWebfluxMethodApplicationITests { - - @Autowired - WebTestClient rest; - - - @Test - public void messageWhenNotAuthenticated() { - this.rest - .get() - .uri("/message") - .exchange() - .expectStatus().isUnauthorized(); - } - - @Test - public void messageWhenUserThenForbidden() { - this.rest - .get() - .uri("/message") - .headers(robsCredentials()) - .exchange() - .expectStatus().isEqualTo(HttpStatus.FORBIDDEN); - } - - @Test - public void messageWhenAdminThenOk() { - this.rest - .get() - .uri("/message") - .headers(adminCredentials()) - .exchange() - .expectStatus().isOk() - .expectBody(String.class).isEqualTo("Hello World!"); - } - - private Consumer robsCredentials() { - return (httpHeaders) -> httpHeaders.setBasicAuth("rob", "rob"); - } - - private Consumer adminCredentials() { - return (httpHeaders) -> httpHeaders.setBasicAuth("admin", "admin"); - } -} - diff --git a/samples/boot/hellowebflux-method/src/main/java/sample/HelloWebfluxMethodApplication.java b/samples/boot/hellowebflux-method/src/main/java/sample/HelloWebfluxMethodApplication.java deleted file mode 100644 index 37aec1d99f..0000000000 --- a/samples/boot/hellowebflux-method/src/main/java/sample/HelloWebfluxMethodApplication.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Rob Winch - * @since 5.0 - */ -@SpringBootApplication -public class HelloWebfluxMethodApplication { - - public static void main(String[] args) { - SpringApplication.run(HelloWebfluxMethodApplication.class, args); - } -} diff --git a/samples/boot/hellowebflux-method/src/main/java/sample/HelloWorldMessageService.java b/samples/boot/hellowebflux-method/src/main/java/sample/HelloWorldMessageService.java deleted file mode 100644 index c6184c830d..0000000000 --- a/samples/boot/hellowebflux-method/src/main/java/sample/HelloWorldMessageService.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.stereotype.Component; -import reactor.core.publisher.Mono; - -/** - * @author Rob Winch - * @since 5.0 - */ -@Component -public class HelloWorldMessageService { - @PreAuthorize("hasRole('ADMIN')") - public Mono findMessage() { - return Mono.just("Hello World!"); - } -} diff --git a/samples/boot/hellowebflux-method/src/main/java/sample/MessageController.java b/samples/boot/hellowebflux-method/src/main/java/sample/MessageController.java deleted file mode 100644 index b8e96e6a45..0000000000 --- a/samples/boot/hellowebflux-method/src/main/java/sample/MessageController.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; -import reactor.core.publisher.Mono; - -/** - * @author Rob Winch - * @since 5.0 - */ -@RestController -public class MessageController { - private final HelloWorldMessageService messages; - - public MessageController(HelloWorldMessageService messages) { - this.messages = messages; - } - - @GetMapping("/message") - public Mono message() { - return this.messages.findMessage(); - } -} diff --git a/samples/boot/hellowebflux-method/src/main/java/sample/SecurityConfig.java b/samples/boot/hellowebflux-method/src/main/java/sample/SecurityConfig.java deleted file mode 100644 index fbbcdc835e..0000000000 --- a/samples/boot/hellowebflux-method/src/main/java/sample/SecurityConfig.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.context.annotation.Bean; -import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity; -import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; -import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.web.server.SecurityWebFilterChain; - -import static org.springframework.security.config.Customizer.withDefaults; - -/** - * @author Rob Winch - * @since 5.0 - */ -@EnableWebFluxSecurity -@EnableReactiveMethodSecurity -public class SecurityConfig { - - @Bean - SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) { - return http - // Demonstrate that method security works - // Best practice to use both for defense in depth - .authorizeExchange((exchanges) -> exchanges - .anyExchange().permitAll() - ) - .httpBasic(withDefaults()) - .build(); - } - - @Bean - public MapReactiveUserDetailsService userDetailsService() { - User.UserBuilder userBuilder = User.withDefaultPasswordEncoder(); - UserDetails rob = userBuilder.username("rob").password("rob").roles("USER").build(); - UserDetails admin = userBuilder.username("admin").password("admin").roles("USER", "ADMIN").build(); - return new MapReactiveUserDetailsService(rob, admin); - } - -} diff --git a/samples/boot/hellowebflux-method/src/test/java/sample/HelloWebfluxMethodApplicationTests.java b/samples/boot/hellowebflux-method/src/test/java/sample/HelloWebfluxMethodApplicationTests.java deleted file mode 100644 index 6a2e2898ed..0000000000 --- a/samples/boot/hellowebflux-method/src/test/java/sample/HelloWebfluxMethodApplicationTests.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockUser; -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity; - -import java.util.function.Consumer; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.ApplicationContext; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * @author Rob Winch - * @since 5.0 - */ -@RunWith(SpringRunner.class) -@SpringBootTest -public class HelloWebfluxMethodApplicationTests { - WebTestClient rest; - - @Autowired - public void setup(ApplicationContext context) { - this.rest = WebTestClient - .bindToApplicationContext(context) - .apply(springSecurity()) - .configureClient() - .build(); - } - - @Test - public void messageWhenNotAuthenticated() { - this.rest - .get() - .uri("/message") - .exchange() - .expectStatus().isUnauthorized(); - } - - @Test - public void messageWhenUserThenForbidden() { - this.rest - .get() - .uri("/message") - .headers(robsCredentials()) - .exchange() - .expectStatus().isEqualTo(HttpStatus.FORBIDDEN); - } - - @Test - public void messageWhenAdminThenOk() { - this.rest - .get() - .uri("/message") - .headers(adminCredentials()) - .exchange() - .expectStatus().isOk() - .expectBody(String.class).isEqualTo("Hello World!"); - } - - @Test - @WithMockUser - public void messageWhenWithMockUserThenForbidden() { - this.rest - .get() - .uri("/message") - .exchange() - .expectStatus().isEqualTo(HttpStatus.FORBIDDEN); - } - - @Test - @WithMockUser(roles = "ADMIN") - public void messageWhenWithMockAdminThenOk() { - this.rest - .get() - .uri("/message") - .exchange() - .expectStatus().isOk() - .expectBody(String.class).isEqualTo("Hello World!"); - } - - @Test - public void messageWhenMutateWithMockUserThenForbidden() { - this.rest - .mutateWith(mockUser()) - .get() - .uri("/message") - .exchange() - .expectStatus().isEqualTo(HttpStatus.FORBIDDEN); - } - - @Test - public void messageWhenMutateWithMockAdminThenOk() { - this.rest - .mutateWith(mockUser().roles("ADMIN")) - .get() - .uri("/message") - .exchange() - .expectStatus().isOk() - .expectBody(String.class).isEqualTo("Hello World!"); - } - - private Consumer robsCredentials() { - return (httpHeaders) -> httpHeaders.setBasicAuth("rob", "rob"); - } - - private Consumer adminCredentials() { - return (httpHeaders) -> httpHeaders.setBasicAuth("admin", "admin"); - } -} diff --git a/samples/boot/hellowebflux-method/src/test/java/sample/HelloWorldMessageServiceTests.java b/samples/boot/hellowebflux-method/src/test/java/sample/HelloWorldMessageServiceTests.java deleted file mode 100644 index d8f2aae925..0000000000 --- a/samples/boot/hellowebflux-method/src/test/java/sample/HelloWorldMessageServiceTests.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.context.junit4.SpringRunner; -import reactor.test.StepVerifier; - -/** - * @author Rob Winch - * @since 5.0 - */ -@RunWith(SpringRunner.class) -@SpringBootTest -public class HelloWorldMessageServiceTests { - @Autowired - HelloWorldMessageService messages; - - @Test - public void messagesWhenNotAuthenticatedThenDenied() { - StepVerifier.create(this.messages.findMessage()) - .expectError(AccessDeniedException.class) - .verify(); - } - - @Test - @WithMockUser - public void messagesWhenUserThenDenied() { - StepVerifier.create(this.messages.findMessage()) - .expectError(AccessDeniedException.class) - .verify(); - } - - @Test - @WithMockUser(roles = "ADMIN") - public void messagesWhenAdminThenOk() { - StepVerifier.create(this.messages.findMessage()) - .expectNext("Hello World!") - .verifyComplete(); - } -} diff --git a/samples/boot/hellowebflux/spring-security-samples-boot-hellowebflux.gradle b/samples/boot/hellowebflux/spring-security-samples-boot-hellowebflux.gradle deleted file mode 100644 index d65d168ad1..0000000000 --- a/samples/boot/hellowebflux/spring-security-samples-boot-hellowebflux.gradle +++ /dev/null @@ -1,11 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-core') - compile project(':spring-security-config') - compile project(':spring-security-web') - compile 'org.springframework.boot:spring-boot-starter-webflux' - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/hellowebflux/src/integration-test/java/sample/HelloWebfluxApplicationITests.java b/samples/boot/hellowebflux/src/integration-test/java/sample/HelloWebfluxApplicationITests.java deleted file mode 100644 index 6d1dda2fac..0000000000 --- a/samples/boot/hellowebflux/src/integration-test/java/sample/HelloWebfluxApplicationITests.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import java.util.function.Consumer; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.HttpHeaders; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * @author Rob Winch - * @since 5.0 - */ -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class HelloWebfluxApplicationITests { - - @Autowired - WebTestClient rest; - - @Test - public void basicWhenNoCredentialsThenUnauthorized() { - this.rest - .get() - .uri("/") - .exchange() - .expectStatus().isUnauthorized(); - } - - @Test - public void basicWhenValidCredentialsThenOk() { - this.rest - .get() - .uri("/") - .headers(userCredentials()) - .exchange() - .expectStatus().isOk() - .expectBody().json("{\"message\":\"Hello user!\"}"); - } - - @Test - public void basicWhenInvalidCredentialsThenUnauthorized() { - this.rest - .get() - .uri("/") - .headers(invalidCredentials()) - .exchange() - .expectStatus().isUnauthorized() - .expectBody().isEmpty(); - } - - private Consumer userCredentials() { - return (httpHeaders) -> httpHeaders.setBasicAuth("user", "user"); - } - - private Consumer invalidCredentials() { - return (httpHeaders) -> httpHeaders.setBasicAuth("user", "INVALID"); - } -} diff --git a/samples/boot/hellowebflux/src/main/java/sample/HelloUserController.java b/samples/boot/hellowebflux/src/main/java/sample/HelloUserController.java deleted file mode 100644 index e06932f222..0000000000 --- a/samples/boot/hellowebflux/src/main/java/sample/HelloUserController.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import java.security.Principal; -import java.util.Collections; -import java.util.Map; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; -import reactor.core.publisher.Mono; - -/** - * @author Rob Winch - * @since 5.0 - */ -@RestController -public class HelloUserController { - - @GetMapping("/") - public Mono> hello(Mono principal) { - return principal - .map(Principal::getName) - .map(this::helloMessage); - } - - private Map helloMessage(String username) { - return Collections.singletonMap("message", "Hello " + username + "!"); - } -} diff --git a/samples/boot/hellowebflux/src/main/java/sample/HelloWebfluxApplication.java b/samples/boot/hellowebflux/src/main/java/sample/HelloWebfluxApplication.java deleted file mode 100644 index b3b27fdf73..0000000000 --- a/samples/boot/hellowebflux/src/main/java/sample/HelloWebfluxApplication.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Rob Winch - * @since 5.0 - */ -@SpringBootApplication -public class HelloWebfluxApplication { - - public static void main(String[] args) { - SpringApplication.run(HelloWebfluxApplication.class, args); - } - -} diff --git a/samples/boot/hellowebflux/src/main/java/sample/HelloWebfluxSecurityConfig.java b/samples/boot/hellowebflux/src/main/java/sample/HelloWebfluxSecurityConfig.java deleted file mode 100644 index e082133afd..0000000000 --- a/samples/boot/hellowebflux/src/main/java/sample/HelloWebfluxSecurityConfig.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.context.annotation.Bean; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; -import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; - -/** - * @author Rob Winch - * @since 5.0 - */ -@EnableWebFluxSecurity -public class HelloWebfluxSecurityConfig { - - @Bean - public MapReactiveUserDetailsService userDetailsService() { - UserDetails user = User.withDefaultPasswordEncoder() - .username("user") - .password("user") - .roles("USER") - .build(); - return new MapReactiveUserDetailsService(user); - } -} diff --git a/samples/boot/hellowebflux/src/test/java/sample/HelloWebfluxApplicationTests.java b/samples/boot/hellowebflux/src/test/java/sample/HelloWebfluxApplicationTests.java deleted file mode 100644 index cc7892116f..0000000000 --- a/samples/boot/hellowebflux/src/test/java/sample/HelloWebfluxApplicationTests.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockUser; -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity; - -import java.util.function.Consumer; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.ApplicationContext; -import org.springframework.http.HttpHeaders; -import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * @author Rob Winch - * @since 5.0 - */ -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureWebTestClient -public class HelloWebfluxApplicationTests { - WebTestClient rest; - - @Autowired - public void setup(ApplicationContext context) { - this.rest = WebTestClient - .bindToApplicationContext(context) - .apply(springSecurity()) - .configureClient() - .build(); - } - - @Test - public void basicWhenNoCredentialsThenUnauthorized() { - this.rest - .get() - .uri("/") - .exchange() - .expectStatus().isUnauthorized(); - } - - @Test - public void basicWhenValidCredentialsThenOk() { - this.rest - .get() - .uri("/") - .headers(userCredentials()) - .exchange() - .expectStatus().isOk() - .expectBody().json("{\"message\":\"Hello user!\"}"); - } - - @Test - public void basicWhenInvalidCredentialsThenUnauthorized() { - this.rest - .get() - .uri("/") - .headers(invalidCredentials()) - .exchange() - .expectStatus().isUnauthorized() - .expectBody().isEmpty(); - } - - @Test - public void mockSupportWhenMutateWithMockUserThenOk() { - this.rest - .mutateWith(mockUser()) - .get() - .uri("/") - .exchange() - .expectStatus().isOk() - .expectBody().json("{\"message\":\"Hello user!\"}"); - } - - @Test - @WithMockUser - public void mockSupportWhenWithMockUserThenOk() { - this.rest - .get() - .uri("/") - .exchange() - .expectStatus().isOk() - .expectBody().json("{\"message\":\"Hello user!\"}"); - } - - private Consumer userCredentials() { - return (httpHeaders) -> httpHeaders.setBasicAuth("user", "user"); - } - - private Consumer invalidCredentials() { - return (httpHeaders) -> httpHeaders.setBasicAuth("user", "INVALID"); - } -} diff --git a/samples/boot/hellowebfluxfn/spring-security-samples-boot-hellowebfluxfn.gradle b/samples/boot/hellowebfluxfn/spring-security-samples-boot-hellowebfluxfn.gradle deleted file mode 100644 index d65d168ad1..0000000000 --- a/samples/boot/hellowebfluxfn/spring-security-samples-boot-hellowebfluxfn.gradle +++ /dev/null @@ -1,11 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-core') - compile project(':spring-security-config') - compile project(':spring-security-web') - compile 'org.springframework.boot:spring-boot-starter-webflux' - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/hellowebfluxfn/src/integration-test/java/sample/HelloWebfluxFnApplicationITests.java b/samples/boot/hellowebfluxfn/src/integration-test/java/sample/HelloWebfluxFnApplicationITests.java deleted file mode 100644 index de42538a78..0000000000 --- a/samples/boot/hellowebfluxfn/src/integration-test/java/sample/HelloWebfluxFnApplicationITests.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import java.util.function.Consumer; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.HttpHeaders; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; -import org.springframework.web.reactive.function.client.ExchangeFilterFunctions; - -/** - * @author Rob Winch - * @since 5.0 - */ -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class HelloWebfluxFnApplicationITests { - - WebTestClient rest; - - @Autowired - public void setRest(WebTestClient rest) { - this.rest = rest - .mutateWith((b, h, c) -> b.filter(ExchangeFilterFunctions.basicAuthentication())); - } - - @Test - public void basicWhenNoCredentialsThenUnauthorized() { - this.rest - .get() - .uri("/") - .exchange() - .expectStatus().isUnauthorized(); - } - - @Test - public void basicWhenValidCredentialsThenOk() { - this.rest - .get() - .uri("/") - .headers(userCredentials()) - .exchange() - .expectStatus().isOk() - .expectBody().json("{\"message\":\"Hello user!\"}"); - } - - @Test - public void basicWhenInvalidCredentialsThenUnauthorized() { - this.rest - .get() - .uri("/") - .headers(invalidCredentials()) - .exchange() - .expectStatus().isUnauthorized() - .expectBody().isEmpty(); - } - - private Consumer userCredentials() { - return (httpHeaders) -> httpHeaders.setBasicAuth("user", "user"); - } - - private Consumer invalidCredentials() { - return (httpHeaders) -> httpHeaders.setBasicAuth("user", "INVALID"); - } -} diff --git a/samples/boot/hellowebfluxfn/src/main/java/sample/HelloUserController.java b/samples/boot/hellowebfluxfn/src/main/java/sample/HelloUserController.java deleted file mode 100644 index e0c0810cee..0000000000 --- a/samples/boot/hellowebfluxfn/src/main/java/sample/HelloUserController.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import java.security.Principal; -import java.util.Collections; - -import reactor.core.publisher.Mono; - -import org.springframework.http.MediaType; -import org.springframework.stereotype.Component; -import org.springframework.web.reactive.function.server.ServerRequest; -import org.springframework.web.reactive.function.server.ServerResponse; - -/** - * @author Rob Winch - * @since 5.0 - */ -@Component -public class HelloUserController { - - public Mono hello(ServerRequest serverRequest) { - return serverRequest.principal() - .map(Principal::getName) - .flatMap((username) -> - ServerResponse.ok() - .contentType(MediaType.APPLICATION_JSON) - .syncBody(Collections.singletonMap("message", "Hello " + username + "!")) - ); - } -} diff --git a/samples/boot/hellowebfluxfn/src/main/java/sample/HelloWebfluxFnApplication.java b/samples/boot/hellowebfluxfn/src/main/java/sample/HelloWebfluxFnApplication.java deleted file mode 100644 index c508e9f554..0000000000 --- a/samples/boot/hellowebfluxfn/src/main/java/sample/HelloWebfluxFnApplication.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import static org.springframework.web.reactive.function.server.RequestPredicates.GET; -import static org.springframework.web.reactive.function.server.RouterFunctions.route; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.ServerResponse; - -/** - * @author Rob Winch - * @since 5.0 - */ -@SpringBootApplication -public class HelloWebfluxFnApplication { - - public static void main(String[] args) { - SpringApplication.run(HelloWebfluxFnApplication.class, args); - } - - @Bean - public RouterFunction routes(HelloUserController userController) { - return route( - GET("/"), userController::hello); - } -} diff --git a/samples/boot/hellowebfluxfn/src/main/java/sample/HelloWebfluxFnSecurityConfig.java b/samples/boot/hellowebfluxfn/src/main/java/sample/HelloWebfluxFnSecurityConfig.java deleted file mode 100644 index bd8c83c553..0000000000 --- a/samples/boot/hellowebfluxfn/src/main/java/sample/HelloWebfluxFnSecurityConfig.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.context.annotation.Bean; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; -import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; - -/** - * @author Rob Winch - * @since 5.0 - */ -@EnableWebFluxSecurity -public class HelloWebfluxFnSecurityConfig { - - @Bean - public MapReactiveUserDetailsService userDetailsService() { - UserDetails user = User.withDefaultPasswordEncoder() - .username("user") - .password("user") - .roles("USER") - .build(); - return new MapReactiveUserDetailsService(user); - } -} diff --git a/samples/boot/hellowebfluxfn/src/test/java/sample/HelloWebfluxFnApplicationTests.java b/samples/boot/hellowebfluxfn/src/test/java/sample/HelloWebfluxFnApplicationTests.java deleted file mode 100644 index 826fe95cf3..0000000000 --- a/samples/boot/hellowebfluxfn/src/test/java/sample/HelloWebfluxFnApplicationTests.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockUser; -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity; - -import java.util.function.Consumer; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.ApplicationContext; -import org.springframework.http.HttpHeaders; -import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * @author Rob Winch - * @since 5.0 - */ -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureWebTestClient -public class HelloWebfluxFnApplicationTests { - - WebTestClient rest; - - @Autowired - public void setup(ApplicationContext context) { - this.rest = WebTestClient - .bindToApplicationContext(context) - .apply(springSecurity()) - .configureClient() - .build(); - } - - @Test - public void basicWhenNoCredentialsThenUnauthorized() { - this.rest - .get() - .uri("/") - .exchange() - .expectStatus().isUnauthorized(); - } - - @Test - public void basicWhenValidCredentialsThenOk() { - this.rest - .get() - .uri("/") - .headers(userCredentials()) - .exchange() - .expectStatus().isOk() - .expectBody().json("{\"message\":\"Hello user!\"}"); - } - - @Test - public void basicWhenInvalidCredentialsThenUnauthorized() { - this.rest - .get() - .uri("/") - .headers(invalidCredentials()) - .exchange() - .expectStatus().isUnauthorized() - .expectBody().isEmpty(); - } - - @Test - public void mockSupportWhenMutateWithMockUserThenOk() { - this.rest - .mutateWith(mockUser()) - .get() - .uri("/") - .exchange() - .expectStatus().isOk() - .expectBody().json("{\"message\":\"Hello user!\"}"); - } - - @Test - @WithMockUser - public void mockSupportWhenWithMockUserThenOk() { - this.rest - .get() - .uri("/") - .exchange() - .expectStatus().isOk() - .expectBody().json("{\"message\":\"Hello user!\"}"); - } - - private Consumer userCredentials() { - return (httpHeaders) -> httpHeaders.setBasicAuth("user", "user"); - } - - private Consumer invalidCredentials() { - return (httpHeaders) -> httpHeaders.setBasicAuth("user", "INVALID"); - } -} diff --git a/samples/boot/helloworld/spring-security-samples-boot-helloworld.gradle b/samples/boot/helloworld/spring-security-samples-boot-helloworld.gradle deleted file mode 100644 index a64426286b..0000000000 --- a/samples/boot/helloworld/spring-security-samples-boot-helloworld.gradle +++ /dev/null @@ -1,12 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-web') - compile 'org.springframework.boot:spring-boot-starter-thymeleaf' - compile 'org.springframework.boot:spring-boot-starter-web' - compile 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/helloworld/src/integration-test/java/org/springframework/security/samples/HelloWorldApplicationTests.java b/samples/boot/helloworld/src/integration-test/java/org/springframework/security/samples/HelloWorldApplicationTests.java deleted file mode 100644 index faeeb015a2..0000000000 --- a/samples/boot/helloworld/src/integration-test/java/org/springframework/security/samples/HelloWorldApplicationTests.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples; - -import org.junit.Test; -import org.junit.runner.RunWith; - -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.mock.web.MockHttpSession; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.MvcResult; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; -import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated; -import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -/** - * - * @author Joe Grandja - */ -@RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -public class HelloWorldApplicationTests { - - @Autowired - private MockMvc mockMvc; - - @Test - public void accessUnprotected() throws Exception { - // @formatter:off - this.mockMvc.perform(get("/index")) - .andExpect(status().isOk()); - // @formatter:on - } - - @Test - public void accessProtectedRedirectsToLogin() throws Exception { - // @formatter:off - MvcResult mvcResult = this.mockMvc.perform(get("/user/index")) - .andExpect(status().is3xxRedirection()) - .andReturn(); - // @formatter:on - - assertThat(mvcResult.getResponse().getRedirectedUrl()).endsWith("/login"); - } - - @Test - public void loginUser() throws Exception { - // @formatter:off - this.mockMvc.perform(formLogin().user("user").password("password")) - .andExpect(authenticated()); - // @formatter:on - } - - @Test - public void loginInvalidUser() throws Exception { - // @formatter:off - this.mockMvc.perform(formLogin().user("invalid").password("invalid")) - .andExpect(unauthenticated()) - .andExpect(status().is3xxRedirection()); - // @formatter:on - } - - @Test - public void loginUserAccessProtected() throws Exception { - // @formatter:off - MvcResult mvcResult = this.mockMvc.perform(formLogin().user("user").password("password")) - .andExpect(authenticated()).andReturn(); - // @formatter:on - - MockHttpSession httpSession = (MockHttpSession) mvcResult.getRequest().getSession(false); - - // @formatter:off - this.mockMvc.perform(get("/user/index").session(httpSession)) - .andExpect(status().isOk()); - // @formatter:on - } - - @Test - public void loginUserValidateLogout() throws Exception { - // @formatter:off - MvcResult mvcResult = this.mockMvc.perform(formLogin().user("user").password("password")) - .andExpect(authenticated()).andReturn(); - // @formatter:on - - MockHttpSession httpSession = (MockHttpSession) mvcResult.getRequest().getSession(false); - - // @formatter:off - this.mockMvc.perform(post("/logout").with(csrf()).session(httpSession)) - .andExpect(unauthenticated()); - this.mockMvc.perform(get("/user/index").session(httpSession)) - .andExpect(unauthenticated()) - .andExpect(status().is3xxRedirection()); - // @formatter:on - } -} diff --git a/samples/boot/helloworld/src/main/java/org/springframework/security/samples/HelloWorldApplication.java b/samples/boot/helloworld/src/main/java/org/springframework/security/samples/HelloWorldApplication.java deleted file mode 100644 index 170bcadef3..0000000000 --- a/samples/boot/helloworld/src/main/java/org/springframework/security/samples/HelloWorldApplication.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Joe Grandja - */ -@SpringBootApplication -public class HelloWorldApplication { - - public static void main(String[] args) { - SpringApplication.run(HelloWorldApplication.class, args); - } - - -} \ No newline at end of file diff --git a/samples/boot/helloworld/src/main/java/org/springframework/security/samples/config/SecurityConfig.java b/samples/boot/helloworld/src/main/java/org/springframework/security/samples/config/SecurityConfig.java deleted file mode 100644 index c3c71cf2fe..0000000000 --- a/samples/boot/helloworld/src/main/java/org/springframework/security/samples/config/SecurityConfig.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.config; - -import org.springframework.context.annotation.Bean; -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.WebSecurityConfigurerAdapter; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.provisioning.InMemoryUserDetailsManager; - -/** - * @author Joe Grandja - */ -@EnableWebSecurity -public class SecurityConfig extends WebSecurityConfigurerAdapter { - - // @formatter:off - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .authorizeRequests((authorize) -> authorize - .antMatchers("/css/**", "/index").permitAll() - .antMatchers("/user/**").hasRole("USER") - ) - .formLogin((formLogin) -> formLogin - .loginPage("/login") - .failureUrl("/login-error") - ); - } - // @formatter:on - - @Bean - public UserDetailsService userDetailsService() { - UserDetails userDetails = User.withDefaultPasswordEncoder() - .username("user") - .password("password") - .roles("USER") - .build(); - return new InMemoryUserDetailsManager(userDetails); - } -} diff --git a/samples/boot/helloworld/src/main/java/org/springframework/security/samples/web/MainController.java b/samples/boot/helloworld/src/main/java/org/springframework/security/samples/web/MainController.java deleted file mode 100644 index 793a8e97eb..0000000000 --- a/samples/boot/helloworld/src/main/java/org/springframework/security/samples/web/MainController.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.web; - -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.RequestMapping; - -/** - * @author Joe Grandja - */ -@Controller -public class MainController { - - @RequestMapping("/") - public String root() { - return "redirect:/index"; - } - - @RequestMapping("/index") - public String index() { - return "index"; - } - - @RequestMapping("/user/index") - public String userIndex() { - return "user/index"; - } - - @RequestMapping("/login") - public String login() { - return "login"; - } - - @RequestMapping("/login-error") - public String loginError(Model model) { - model.addAttribute("loginError", true); - return "login"; - } - -} diff --git a/samples/boot/helloworld/src/main/resources/application.yml b/samples/boot/helloworld/src/main/resources/application.yml deleted file mode 100644 index b59d86df49..0000000000 --- a/samples/boot/helloworld/src/main/resources/application.yml +++ /dev/null @@ -1,12 +0,0 @@ -server: - port: 8080 - -logging: - level: - root: WARN - org.springframework.web: INFO - org.springframework.security: INFO - -spring: - thymeleaf: - cache: false diff --git a/samples/boot/helloworld/src/main/resources/static/css/main.css b/samples/boot/helloworld/src/main/resources/static/css/main.css deleted file mode 100644 index 5e6687a387..0000000000 --- a/samples/boot/helloworld/src/main/resources/static/css/main.css +++ /dev/null @@ -1,13 +0,0 @@ -body { - font-family: sans; - font-size: 1em; -} - -p.error { - font-weight: bold; - color: red; -} - -div.logout { - float: right; -} \ No newline at end of file diff --git a/samples/boot/helloworld/src/main/resources/templates/index.html b/samples/boot/helloworld/src/main/resources/templates/index.html deleted file mode 100644 index 05fad12033..0000000000 --- a/samples/boot/helloworld/src/main/resources/templates/index.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - Hello Spring Security - - - - -
- Logged in user: | - Roles: -
-
- -
-
-
-

Hello Spring Security

-

This is an unsecured page, but you can access the secured pages after authenticating.

- - - diff --git a/samples/boot/helloworld/src/main/resources/templates/login.html b/samples/boot/helloworld/src/main/resources/templates/login.html deleted file mode 100644 index cec2b5b0da..0000000000 --- a/samples/boot/helloworld/src/main/resources/templates/login.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - Login page - - - - -

Login page

-

Example user: user / password

-

Wrong user or password

-
- : -
- : -
- -
-

Back to home page

- - diff --git a/samples/boot/helloworld/src/main/resources/templates/user/index.html b/samples/boot/helloworld/src/main/resources/templates/user/index.html deleted file mode 100644 index 53dd9319a5..0000000000 --- a/samples/boot/helloworld/src/main/resources/templates/user/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - Hello Spring Security - - - - -
-

This is a secured page!

-

Back to home page

- - diff --git a/samples/boot/insecure/spring-security-samples-boot-insecure.gradle b/samples/boot/insecure/spring-security-samples-boot-insecure.gradle deleted file mode 100644 index 556ebbb053..0000000000 --- a/samples/boot/insecure/spring-security-samples-boot-insecure.gradle +++ /dev/null @@ -1,8 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile 'org.springframework.boot:spring-boot-starter-thymeleaf' - compile 'org.springframework.boot:spring-boot-starter-web' - - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/insecure/src/integration-test/java/org/springframework/security/samples/InsecureApplicationTests.java b/samples/boot/insecure/src/integration-test/java/org/springframework/security/samples/InsecureApplicationTests.java deleted file mode 100644 index f2c7542e5b..0000000000 --- a/samples/boot/insecure/src/integration-test/java/org/springframework/security/samples/InsecureApplicationTests.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples; - -import org.junit.Test; -import org.junit.runner.RunWith; - -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.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.web.servlet.MockMvc; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -/** - * - * @author Joe Grandja - */ -@RunWith(SpringJUnit4ClassRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -public class InsecureApplicationTests { - - @Autowired - private MockMvc mockMvc; - - @Test - public void accessUnprotected() throws Exception { - this.mockMvc.perform(get("/index")).andExpect(status().isOk()); - } - -} diff --git a/samples/boot/insecure/src/main/java/org/springframework/security/samples/InsecureApplication.java b/samples/boot/insecure/src/main/java/org/springframework/security/samples/InsecureApplication.java deleted file mode 100644 index aab24fa9d3..0000000000 --- a/samples/boot/insecure/src/main/java/org/springframework/security/samples/InsecureApplication.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2012-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Joe Grandja - */ -@SpringBootApplication -public class InsecureApplication { - - public static void main(String[] args) { - SpringApplication.run(InsecureApplication.class, args); - } - - -} diff --git a/samples/boot/insecure/src/main/java/org/springframework/security/samples/web/MainController.java b/samples/boot/insecure/src/main/java/org/springframework/security/samples/web/MainController.java deleted file mode 100644 index f7de44adcc..0000000000 --- a/samples/boot/insecure/src/main/java/org/springframework/security/samples/web/MainController.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.web; - -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; - -/** - * @author Joe Grandja - */ -@Controller -public class MainController { - - @RequestMapping("/") - public String root() { - return "redirect:/index"; - } - - @RequestMapping("/index") - public String index() { - return "index"; - } - - @RequestMapping("/user/index") - public String userIndex() { - return "user/index"; - } - - @RequestMapping(value = "/login") - public String login() { - return "login"; - } - - @RequestMapping(value = "/login", method = RequestMethod.POST) - public String postLogin() { - // TODO Enable form login with Spring Security (trigger error for now) - return "redirect:/login-error"; - } - - @RequestMapping("/login-error") - public String loginError(Model model) { - model.addAttribute("loginError", true); - return "login"; - } - -} diff --git a/samples/boot/insecure/src/main/resources/application.yml b/samples/boot/insecure/src/main/resources/application.yml deleted file mode 100644 index 0254088803..0000000000 --- a/samples/boot/insecure/src/main/resources/application.yml +++ /dev/null @@ -1,11 +0,0 @@ -server: - port: 8080 - -logging: - level: - root: WARN - org.springframework.web: INFO - -spring: - thymeleaf: - cache: false diff --git a/samples/boot/insecure/src/main/resources/static/css/main.css b/samples/boot/insecure/src/main/resources/static/css/main.css deleted file mode 100644 index 5e6687a387..0000000000 --- a/samples/boot/insecure/src/main/resources/static/css/main.css +++ /dev/null @@ -1,13 +0,0 @@ -body { - font-family: sans; - font-size: 1em; -} - -p.error { - font-weight: bold; - color: red; -} - -div.logout { - float: right; -} \ No newline at end of file diff --git a/samples/boot/insecure/src/main/resources/templates/index.html b/samples/boot/insecure/src/main/resources/templates/index.html deleted file mode 100644 index ee9ccec618..0000000000 --- a/samples/boot/insecure/src/main/resources/templates/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - Hello Spring Security - - - - -

Hello Spring Security

-

This is an unsecured page, but you can access the secured pages after authenticating.

- - - diff --git a/samples/boot/insecure/src/main/resources/templates/login.html b/samples/boot/insecure/src/main/resources/templates/login.html deleted file mode 100644 index cec2b5b0da..0000000000 --- a/samples/boot/insecure/src/main/resources/templates/login.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - Login page - - - - -

Login page

-

Example user: user / password

-

Wrong user or password

-
- : -
- : -
- -
-

Back to home page

- - diff --git a/samples/boot/insecure/src/main/resources/templates/user/index.html b/samples/boot/insecure/src/main/resources/templates/user/index.html deleted file mode 100644 index 3fd4ccc1a3..0000000000 --- a/samples/boot/insecure/src/main/resources/templates/user/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - Hello Spring Security - - - - -

TODO Secure this

-

We would like to secure this page

-

Back to home page

- - diff --git a/samples/boot/kotlin-webflux/spring-security-samples-boot-kotlin-webflux.gradle.kts b/samples/boot/kotlin-webflux/spring-security-samples-boot-kotlin-webflux.gradle.kts deleted file mode 100644 index 20eb7b4060..0000000000 --- a/samples/boot/kotlin-webflux/spring-security-samples-boot-kotlin-webflux.gradle.kts +++ /dev/null @@ -1,41 +0,0 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - -plugins { - id("io.spring.convention.spring-sample-boot") - kotlin("jvm") - kotlin("plugin.spring") version "1.3.71" -} - -repositories { - mavenCentral() -} - -dependencies { - implementation(project(":spring-security-core")) - implementation(project(":spring-security-config")) - implementation(project(":spring-security-web")) - implementation("org.springframework.boot:spring-boot-starter-webflux") - implementation("org.springframework.boot:spring-boot-starter-thymeleaf") - implementation("org.thymeleaf.extras:thymeleaf-extras-springsecurity5") - implementation("io.projectreactor.kotlin:reactor-kotlin-extensions") - implementation("org.jetbrains.kotlin:kotlin-reflect") - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor") - - testImplementation(project(":spring-security-test")) - testImplementation("org.springframework.boot:spring-boot-starter-test") { - exclude(group = "org.junit.vintage", module = "junit-vintage-engine") - } - testImplementation("io.projectreactor:reactor-test") -} - -tasks.withType { - useJUnitPlatform() -} - -tasks.withType { - kotlinOptions { - freeCompilerArgs = listOf("-Xjsr305=strict") - jvmTarget = "1.8" - } -} diff --git a/samples/boot/kotlin-webflux/src/main/kotlin/org/springframework/security/samples/KotlinWebfluxApplication.kt b/samples/boot/kotlin-webflux/src/main/kotlin/org/springframework/security/samples/KotlinWebfluxApplication.kt deleted file mode 100644 index 572be2a6e3..0000000000 --- a/samples/boot/kotlin-webflux/src/main/kotlin/org/springframework/security/samples/KotlinWebfluxApplication.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples - -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -class KotlinWebfluxApplication - -fun main(args: Array) { - runApplication(*args) -} diff --git a/samples/boot/kotlin-webflux/src/main/kotlin/org/springframework/security/samples/config/SecurityConfig.kt b/samples/boot/kotlin-webflux/src/main/kotlin/org/springframework/security/samples/config/SecurityConfig.kt deleted file mode 100644 index fcdb5fdcde..0000000000 --- a/samples/boot/kotlin-webflux/src/main/kotlin/org/springframework/security/samples/config/SecurityConfig.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.config - -import org.springframework.context.annotation.Bean -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity -import org.springframework.security.config.web.server.ServerHttpSecurity -import org.springframework.security.config.web.server.invoke -import org.springframework.security.core.userdetails.MapReactiveUserDetailsService -import org.springframework.security.core.userdetails.ReactiveUserDetailsService -import org.springframework.security.core.userdetails.User -import org.springframework.security.web.server.SecurityWebFilterChain - -@EnableWebFluxSecurity -class SecurityConfig { - - @Bean - fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain { - return http { - authorizeExchange { - authorize("/log-in", permitAll) - authorize("/", permitAll) - authorize("/css/**", permitAll) - authorize("/user/**", hasAuthority("ROLE_USER")) - } - formLogin { - loginPage = "/log-in" - } - } - } - - @Bean - fun userDetailsService(): ReactiveUserDetailsService { - val userDetails = User.withDefaultPasswordEncoder() - .username("user") - .password("password") - .roles("USER") - .build() - return MapReactiveUserDetailsService(userDetails) - } -} diff --git a/samples/boot/kotlin-webflux/src/main/kotlin/org/springframework/security/samples/web/MainController.kt b/samples/boot/kotlin-webflux/src/main/kotlin/org/springframework/security/samples/web/MainController.kt deleted file mode 100644 index 991c0195c0..0000000000 --- a/samples/boot/kotlin-webflux/src/main/kotlin/org/springframework/security/samples/web/MainController.kt +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.web - -import org.springframework.stereotype.Controller -import org.springframework.web.bind.annotation.GetMapping - -@Controller -class MainController { - - @GetMapping("/") - fun index(): String { - return "index" - } - - @GetMapping("/user/index") - fun userIndex(): String { - return "user/index" - } - - @GetMapping("/log-in") - fun login(): String { - return "login" - } -} diff --git a/samples/boot/kotlin-webflux/src/main/resources/application.yml b/samples/boot/kotlin-webflux/src/main/resources/application.yml deleted file mode 100644 index 8c01e005bc..0000000000 --- a/samples/boot/kotlin-webflux/src/main/resources/application.yml +++ /dev/null @@ -1,6 +0,0 @@ -server: - port: 8080 - -spring: - thymeleaf: - cache: false diff --git a/samples/boot/kotlin-webflux/src/main/resources/css/main.css b/samples/boot/kotlin-webflux/src/main/resources/css/main.css deleted file mode 100644 index de0941ecd5..0000000000 --- a/samples/boot/kotlin-webflux/src/main/resources/css/main.css +++ /dev/null @@ -1,8 +0,0 @@ -body { - font-family: sans; - font-size: 1em; -} - -div.logout { - float: right; -} diff --git a/samples/boot/kotlin-webflux/src/main/resources/templates/index.html b/samples/boot/kotlin-webflux/src/main/resources/templates/index.html deleted file mode 100644 index f637854f04..0000000000 --- a/samples/boot/kotlin-webflux/src/main/resources/templates/index.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - Hello Spring Security - - - - -
- Logged in user: | - Roles: -
-
- -
-
-
-

Hello Spring Security

-

This is an unsecured page, but you can access the secured pages after authenticating.

- - - diff --git a/samples/boot/kotlin-webflux/src/main/resources/templates/login.html b/samples/boot/kotlin-webflux/src/main/resources/templates/login.html deleted file mode 100644 index 2ee9216937..0000000000 --- a/samples/boot/kotlin-webflux/src/main/resources/templates/login.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - Login page - - - - -

Login page

-

Example user: user / password

-
- : -
- : -
- -
-

Back to home page

- - diff --git a/samples/boot/kotlin-webflux/src/main/resources/templates/user/index.html b/samples/boot/kotlin-webflux/src/main/resources/templates/user/index.html deleted file mode 100644 index 393f6d3705..0000000000 --- a/samples/boot/kotlin-webflux/src/main/resources/templates/user/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - Hello Spring Security - - - - -
-

This is a secured page!

-

Back to home page

- - diff --git a/samples/boot/kotlin-webflux/src/test/kotlin/org/springframework/security/samples/KotlinWebfluxApplicationTests.kt b/samples/boot/kotlin-webflux/src/test/kotlin/org/springframework/security/samples/KotlinWebfluxApplicationTests.kt deleted file mode 100644 index fc126e58b7..0000000000 --- a/samples/boot/kotlin-webflux/src/test/kotlin/org/springframework/security/samples/KotlinWebfluxApplicationTests.kt +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples - -import org.junit.jupiter.api.Test -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.context.ApplicationContext -import org.springframework.test.web.reactive.server.WebTestClient -import org.springframework.security.test.context.support.WithMockUser - -@SpringBootTest -class KotlinWebfluxApplicationTests { - - lateinit var rest: WebTestClient - - @Autowired - fun setup(context: ApplicationContext) { - rest = WebTestClient - .bindToApplicationContext(context) - .configureClient() - .build() - } - - @Test - fun `index page is not protected`() { - rest - .get() - .uri("/") - .exchange() - .expectStatus().isOk - } - - @Test - fun `protected page when unauthenticated then redirects to login `() { - rest - .get() - .uri("/user/index") - .exchange() - .expectStatus().is3xxRedirection - .expectHeader().valueEquals("Location", "/log-in") - } - - @Test - @WithMockUser - fun `protected page can be accessed when authenticated`() { - rest - .get() - .uri("/user/index") - .exchange() - .expectStatus().isOk - } -} diff --git a/samples/boot/kotlin/spring-security-samples-boot-kotlin.gradle.kts b/samples/boot/kotlin/spring-security-samples-boot-kotlin.gradle.kts deleted file mode 100644 index bd841b8b71..0000000000 --- a/samples/boot/kotlin/spring-security-samples-boot-kotlin.gradle.kts +++ /dev/null @@ -1,31 +0,0 @@ -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - -plugins { - id("io.spring.convention.spring-sample-boot") - kotlin("jvm") - kotlin("plugin.spring") version "1.3.71" -} - -repositories { - mavenCentral() -} - -dependencies { - implementation(project(":spring-security-core")) - implementation(project(":spring-security-config")) - implementation(project(":spring-security-web")) - implementation("org.springframework.boot:spring-boot-starter-web") - implementation("org.springframework.boot:spring-boot-starter-thymeleaf") - implementation("org.thymeleaf.extras:thymeleaf-extras-springsecurity5") - implementation("org.jetbrains.kotlin:kotlin-reflect") - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") - testImplementation(project(":spring-security-test")) - testImplementation("org.springframework.boot:spring-boot-starter-test") -} - -tasks.withType { - kotlinOptions { - freeCompilerArgs = listOf("-Xjsr305=strict") - jvmTarget = "1.8" - } -} diff --git a/samples/boot/kotlin/src/main/kotlin/org/springframework/security/samples/KotlinApplication.kt b/samples/boot/kotlin/src/main/kotlin/org/springframework/security/samples/KotlinApplication.kt deleted file mode 100644 index 1d7c7b28f2..0000000000 --- a/samples/boot/kotlin/src/main/kotlin/org/springframework/security/samples/KotlinApplication.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.security.samples - -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -/** - * @author Eleftheria Stein - */ -@SpringBootApplication -class KotlinApplication - -fun main(args: Array) { - runApplication(*args) -} diff --git a/samples/boot/kotlin/src/main/kotlin/org/springframework/security/samples/config/SecurityConfig.kt b/samples/boot/kotlin/src/main/kotlin/org/springframework/security/samples/config/SecurityConfig.kt deleted file mode 100644 index 043f29ecae..0000000000 --- a/samples/boot/kotlin/src/main/kotlin/org/springframework/security/samples/config/SecurityConfig.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.config - -import org.springframework.context.annotation.Bean -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.WebSecurityConfigurerAdapter -import org.springframework.security.config.web.servlet.invoke -import org.springframework.security.core.userdetails.User -import org.springframework.security.core.userdetails.UserDetailsService -import org.springframework.security.provisioning.InMemoryUserDetailsManager - -/** - * @author Eleftheria Stein - */ -@EnableWebSecurity -class SecurityConfig : WebSecurityConfigurerAdapter() { - - override fun configure(http: HttpSecurity) { - http { - authorizeRequests { - authorize("/css/**", permitAll) - authorize("/user/**", hasAuthority("ROLE_USER")) - } - formLogin { - loginPage = "/log-in" - } - } - } - - @Bean - public override fun userDetailsService(): UserDetailsService { - val userDetails = User.withDefaultPasswordEncoder() - .username("user") - .password("password") - .roles("USER") - .build() - return InMemoryUserDetailsManager(userDetails) - } -} diff --git a/samples/boot/kotlin/src/main/kotlin/org/springframework/security/samples/web/MainController.kt b/samples/boot/kotlin/src/main/kotlin/org/springframework/security/samples/web/MainController.kt deleted file mode 100644 index e8c8128ad8..0000000000 --- a/samples/boot/kotlin/src/main/kotlin/org/springframework/security/samples/web/MainController.kt +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.web - -import org.springframework.stereotype.Controller -import org.springframework.web.bind.annotation.GetMapping - -/** - * @author Eleftheria Stein - */ -@Controller -class MainController { - - @GetMapping("/") - fun index(): String { - return "index" - } - - @GetMapping("/user/index") - fun userIndex(): String { - return "user/index" - } - - @GetMapping("/log-in") - fun login(): String { - return "login" - } -} diff --git a/samples/boot/kotlin/src/main/resources/application.yml b/samples/boot/kotlin/src/main/resources/application.yml deleted file mode 100644 index 8c01e005bc..0000000000 --- a/samples/boot/kotlin/src/main/resources/application.yml +++ /dev/null @@ -1,6 +0,0 @@ -server: - port: 8080 - -spring: - thymeleaf: - cache: false diff --git a/samples/boot/kotlin/src/main/resources/static/css/main.css b/samples/boot/kotlin/src/main/resources/static/css/main.css deleted file mode 100644 index de0941ecd5..0000000000 --- a/samples/boot/kotlin/src/main/resources/static/css/main.css +++ /dev/null @@ -1,8 +0,0 @@ -body { - font-family: sans; - font-size: 1em; -} - -div.logout { - float: right; -} diff --git a/samples/boot/kotlin/src/main/resources/templates/index.html b/samples/boot/kotlin/src/main/resources/templates/index.html deleted file mode 100644 index c30f4a8292..0000000000 --- a/samples/boot/kotlin/src/main/resources/templates/index.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - Hello Spring Security - - - - -
- Logged in user: | - Roles: -
-
- -
-
-
-

Hello Spring Security

-

This is an unsecured page, but you can access the secured pages after authenticating.

- - - diff --git a/samples/boot/kotlin/src/main/resources/templates/login.html b/samples/boot/kotlin/src/main/resources/templates/login.html deleted file mode 100644 index 2ee9216937..0000000000 --- a/samples/boot/kotlin/src/main/resources/templates/login.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - Login page - - - - -

Login page

-

Example user: user / password

-
- : -
- : -
- -
-

Back to home page

- - diff --git a/samples/boot/kotlin/src/main/resources/templates/user/index.html b/samples/boot/kotlin/src/main/resources/templates/user/index.html deleted file mode 100644 index b36caed027..0000000000 --- a/samples/boot/kotlin/src/main/resources/templates/user/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - Hello Spring Security - - - - -
-

This is a secured page!

-

Back to home page

- - diff --git a/samples/boot/kotlin/src/test/kotlin/org/springframework/security/samples/KotlinApplicationTests.kt b/samples/boot/kotlin/src/test/kotlin/org/springframework/security/samples/KotlinApplicationTests.kt deleted file mode 100644 index 393bb0f2e2..0000000000 --- a/samples/boot/kotlin/src/test/kotlin/org/springframework/security/samples/KotlinApplicationTests.kt +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples - -import org.assertj.core.api.Assertions.assertThat -import org.junit.Test -import org.junit.runner.RunWith -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.mock.web.MockHttpSession -import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin -import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated -import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated -import org.springframework.test.context.junit4.SpringRunner -import org.springframework.test.web.servlet.MockMvc -import org.springframework.test.web.servlet.get -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status - -@RunWith(SpringRunner::class) -@SpringBootTest -@AutoConfigureMockMvc -class KotlinApplicationTests { - - @Autowired - private lateinit var mockMvc: MockMvc - - @Test - fun `index page is not protected`() { - this.mockMvc.get("/") - .andExpect { - status { isOk() } - } - } - - @Test - fun `protected page redirects to login`() { - val mvcResult = this.mockMvc.get("/user/index") - .andExpect { status { is3xxRedirection() } } - .andReturn() - - assertThat(mvcResult.response.redirectedUrl).endsWith("/log-in") - } - - @Test - fun `valid user permitted to log in`() { - this.mockMvc.perform(formLogin("/log-in").user("user").password("password")) - .andExpect(authenticated()) - } - - @Test - fun `invalid user not permitted to log in`() { - this.mockMvc.perform(formLogin("/log-in").user("invalid").password("invalid")) - .andExpect(unauthenticated()) - .andExpect(status().is3xxRedirection) - } - - @Test - fun `logged in user can access protected page`() { - val mvcResult = this.mockMvc.perform(formLogin("/log-in").user("user").password("password")) - .andExpect(authenticated()).andReturn() - - val httpSession = mvcResult.request.getSession(false) as MockHttpSession - - this.mockMvc.get("/user/index") { - session = httpSession - }.andExpect { - status { isOk() } - } - } -} diff --git a/samples/boot/oauth2authorizationserver/README.adoc b/samples/boot/oauth2authorizationserver/README.adoc deleted file mode 100644 index e056a21b17..0000000000 --- a/samples/boot/oauth2authorizationserver/README.adoc +++ /dev/null @@ -1,39 +0,0 @@ -= OAuth 2.0 Authorization Server Sample - -This sample demonstrates an Authorization Server that supports a simple, static JWK Set. - -It's useful for working with the other samples in the library that want to point to an Authorization Server. - -== 1. Running the server - -To run the server, do: - -```bash -./gradlew bootRun -``` - -Or import the project into your IDE and run `OAuth2AuthorizationServerApplication` from there. - -Once it is up, this request asks for a token with the "message:read" scope: - -```bash -curl reader:secret@localhost:8081/oauth/token -d grant_type=password -d username=subject -d password=password -``` - -Which will respond with something like: - -```json -{ - "access_token":"eyJhbGciOiJSUzI1NiIsI...Fhq4RIVyA4ZAkC7T1aZbKAQ", - "token_type":"bearer", - "expires_in":599999999, - "scope":"message:read", - "jti":"8a425df7-f4c9-4ca4-be12-0136c3015da0" -} -``` - -You can also do the same with the `writer` client: - -```bash -curl writer:secret@localhost:8081/oauth/token -d grant_type=password -d username=subject -d password=password -``` diff --git a/samples/boot/oauth2authorizationserver/spring-security-samples-boot-oauth2authorizationserver.gradle b/samples/boot/oauth2authorizationserver/spring-security-samples-boot-oauth2authorizationserver.gradle deleted file mode 100644 index 3b2df4e605..0000000000 --- a/samples/boot/oauth2authorizationserver/spring-security-samples-boot-oauth2authorizationserver.gradle +++ /dev/null @@ -1,14 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile 'org.springframework.boot:spring-boot-starter-web' - compile 'org.springframework.boot:spring-boot-starter-security' - compile "org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:${springBootVersion}" - - compile 'javax.xml.bind:jaxb-api' - compile 'com.sun.xml.bind:jaxb-core' - compile 'com.sun.xml.bind:jaxb-impl' - compile 'com.nimbusds:nimbus-jose-jwt' - - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/oauth2authorizationserver/src/main/java/sample/AuthorizationServerConfiguration.java b/samples/boot/oauth2authorizationserver/src/main/java/sample/AuthorizationServerConfiguration.java deleted file mode 100644 index 4b20b0c88c..0000000000 --- a/samples/boot/oauth2authorizationserver/src/main/java/sample/AuthorizationServerConfiguration.java +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import java.math.BigInteger; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.RSAPrivateKeySpec; -import java.security.spec.RSAPublicKeySpec; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.stream.Collectors; - -import com.nimbusds.jose.jwk.JWKSet; -import com.nimbusds.jose.jwk.RSAKey; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.oauth2.common.OAuth2AccessToken; -import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; -import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; -import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; -import org.springframework.security.oauth2.provider.OAuth2Authentication; -import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpoint; -import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; -import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter; -import org.springframework.security.oauth2.provider.token.TokenStore; -import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; -import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; -import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; -import org.springframework.security.provisioning.InMemoryUserDetailsManager; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; - -/** - * An instance of Legacy Authorization Server (spring-security-oauth2) that uses a single, - * not-rotating key and exposes a JWK endpoint. - * - * See - * - * Spring Security OAuth Autoconfig's documentation for additional detail - * - * @author Josh Cummings - * @since 5.1 - */ -@EnableAuthorizationServer -@Configuration -public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { - - AuthenticationManager authenticationManager; - KeyPair keyPair; - boolean jwtEnabled; - - public AuthorizationServerConfiguration( - AuthenticationConfiguration authenticationConfiguration, - KeyPair keyPair, - @Value("${security.oauth2.authorizationserver.jwt.enabled:true}") boolean jwtEnabled) throws Exception { - - this.authenticationManager = authenticationConfiguration.getAuthenticationManager(); - this.keyPair = keyPair; - this.jwtEnabled = jwtEnabled; - } - - @Override - public void configure(ClientDetailsServiceConfigurer clients) - throws Exception { - // @formatter:off - clients.inMemory() - .withClient("reader") - .authorizedGrantTypes("password") - .secret("{noop}secret") - .scopes("message:read") - .accessTokenValiditySeconds(600_000_000) - .and() - .withClient("writer") - .authorizedGrantTypes("password") - .secret("{noop}secret") - .scopes("message:write") - .accessTokenValiditySeconds(600_000_000) - .and() - .withClient("noscopes") - .authorizedGrantTypes("password") - .secret("{noop}secret") - .scopes("none") - .accessTokenValiditySeconds(600_000_000); - // @formatter:on - } - - @Override - public void configure(AuthorizationServerEndpointsConfigurer endpoints) { - // @formatter:off - endpoints - .authenticationManager(this.authenticationManager) - .tokenStore(tokenStore()); - - if (this.jwtEnabled) { - endpoints - .accessTokenConverter(accessTokenConverter()); - } - // @formatter:on - } - - @Bean - public TokenStore tokenStore() { - if (this.jwtEnabled) { - return new JwtTokenStore(accessTokenConverter()); - } else { - return new InMemoryTokenStore(); - } - } - - @Bean - public JwtAccessTokenConverter accessTokenConverter() { - JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); - converter.setKeyPair(this.keyPair); - - DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter(); - accessTokenConverter.setUserTokenConverter(new SubjectAttributeUserTokenConverter()); - converter.setAccessTokenConverter(accessTokenConverter); - - return converter; - } -} - -/** - * For configuring the end users recognized by this Authorization Server - */ -@Configuration -class UserConfig extends WebSecurityConfigurerAdapter { - - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .authorizeRequests() - .mvcMatchers("/.well-known/jwks.json").permitAll() - .anyRequest().authenticated() - .and() - .httpBasic() - .and() - .csrf().ignoringRequestMatchers((request) -> "/introspect".equals(request.getRequestURI())); - } - - @Bean - @Override - public UserDetailsService userDetailsService() { - return new InMemoryUserDetailsManager( - User.withDefaultPasswordEncoder() - .username("subject") - .password("password") - .roles("USER") - .build()); - } -} - -/** - * Legacy Authorization Server (spring-security-oauth2) does not support any - * Token Introspection endpoint. - * - * This class adds ad-hoc support in order to better support the other samples in the repo. - */ -@FrameworkEndpoint -class IntrospectEndpoint { - TokenStore tokenStore; - - IntrospectEndpoint(TokenStore tokenStore) { - this.tokenStore = tokenStore; - } - - @PostMapping("/introspect") - @ResponseBody - public Map introspect(@RequestParam("token") String token) { - OAuth2AccessToken accessToken = this.tokenStore.readAccessToken(token); - Map attributes = new HashMap<>(); - if (accessToken == null || accessToken.isExpired()) { - attributes.put("active", false); - return attributes; - } - - OAuth2Authentication authentication = this.tokenStore.readAuthentication(token); - - attributes.put("active", true); - attributes.put("exp", accessToken.getExpiration().getTime()); - attributes.put("scope", accessToken.getScope().stream().collect(Collectors.joining(" "))); - attributes.put("sub", authentication.getName()); - - return attributes; - } -} - -/** - * Legacy Authorization Server (spring-security-oauth2) does not support any - * JWK Set endpoint. - * - * This class adds ad-hoc support in order to better support the other samples in the repo. - */ -@FrameworkEndpoint -class JwkSetEndpoint { - KeyPair keyPair; - - JwkSetEndpoint(KeyPair keyPair) { - this.keyPair = keyPair; - } - - @GetMapping("/.well-known/jwks.json") - @ResponseBody - public Map getKey() { - RSAPublicKey publicKey = (RSAPublicKey) this.keyPair.getPublic(); - RSAKey key = new RSAKey.Builder(publicKey).build(); - return new JWKSet(key).toJSONObject(); - } -} - -/** - * An Authorization Server will more typically have a key rotation strategy, and the keys will not - * be hard-coded into the application code. - * - * For simplicity, though, this sample doesn't demonstrate key rotation. - */ -@Configuration -class KeyConfig { - @Bean - KeyPair keyPair() { - try { - String privateExponent = "3851612021791312596791631935569878540203393691253311342052463788814433805390794604753109719790052408607029530149004451377846406736413270923596916756321977922303381344613407820854322190592787335193581632323728135479679928871596911841005827348430783250026013354350760878678723915119966019947072651782000702927096735228356171563532131162414366310012554312756036441054404004920678199077822575051043273088621405687950081861819700809912238863867947415641838115425624808671834312114785499017269379478439158796130804789241476050832773822038351367878951389438751088021113551495469440016698505614123035099067172660197922333993"; - String modulus = "18044398961479537755088511127417480155072543594514852056908450877656126120801808993616738273349107491806340290040410660515399239279742407357192875363433659810851147557504389760192273458065587503508596714389889971758652047927503525007076910925306186421971180013159326306810174367375596043267660331677530921991343349336096643043840224352451615452251387611820750171352353189973315443889352557807329336576421211370350554195530374360110583327093711721857129170040527236951522127488980970085401773781530555922385755722534685479501240842392531455355164896023070459024737908929308707435474197069199421373363801477026083786683"; - String exponent = "65537"; - - RSAPublicKeySpec publicSpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(exponent)); - RSAPrivateKeySpec privateSpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(privateExponent)); - KeyFactory factory = KeyFactory.getInstance("RSA"); - return new KeyPair(factory.generatePublic(publicSpec), factory.generatePrivate(privateSpec)); - } catch ( Exception e ) { - throw new IllegalArgumentException(e); - } - } -} - -/** - * Legacy Authorization Server does not support a custom name for the user parameter, so we'll need - * to extend the default. By default, it uses the attribute {@code user_name}, though it would be - * better to adhere to the {@code sub} property defined in the - * JWT Specification. - */ -class SubjectAttributeUserTokenConverter extends DefaultUserAuthenticationConverter { - @Override - public Map convertUserAuthentication(Authentication authentication) { - Map response = new LinkedHashMap<>(); - response.put("sub", authentication.getName()); - if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) { - response.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities())); - } - return response; - } -} diff --git a/samples/boot/oauth2authorizationserver/src/main/java/sample/OAuth2AuthorizationServerApplication.java b/samples/boot/oauth2authorizationserver/src/main/java/sample/OAuth2AuthorizationServerApplication.java deleted file mode 100644 index 13602ec74e..0000000000 --- a/samples/boot/oauth2authorizationserver/src/main/java/sample/OAuth2AuthorizationServerApplication.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Josh Cummings - */ -@SpringBootApplication -public class OAuth2AuthorizationServerApplication { - - public static void main(String[] args) { - SpringApplication.run(OAuth2AuthorizationServerApplication.class, args); - } -} diff --git a/samples/boot/oauth2authorizationserver/src/main/resources/application.yml b/samples/boot/oauth2authorizationserver/src/main/resources/application.yml deleted file mode 100644 index b0b10a294f..0000000000 --- a/samples/boot/oauth2authorizationserver/src/main/resources/application.yml +++ /dev/null @@ -1,3 +0,0 @@ -server.port: 8081 - -# security.oauth2.authorizationserver.jwt.enabled: false diff --git a/samples/boot/oauth2authorizationserver/src/test/java/sample/OAuth2AuthorizationServerApplicationTests.java b/samples/boot/oauth2authorizationserver/src/test/java/sample/OAuth2AuthorizationServerApplicationTests.java deleted file mode 100644 index 05377bf3f8..0000000000 --- a/samples/boot/oauth2authorizationserver/src/test/java/sample/OAuth2AuthorizationServerApplicationTests.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; - -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.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -/** - * Tests for {@link OAuth2AuthorizationServerApplication} - * - * @author Josh Cummings - */ -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -public class OAuth2AuthorizationServerApplicationTests { - - @Autowired - MockMvc mvc; - - @Test - public void requestTokenWhenUsingPasswordGrantTypeThenOk() - throws Exception { - - this.mvc.perform(post("/oauth/token") - .param("grant_type", "password") - .param("username", "subject") - .param("password", "password") - .header("Authorization", "Basic cmVhZGVyOnNlY3JldA==")) - .andExpect(status().isOk()); - } - - @Test - public void requestJwkSetWhenUsingDefaultsThenOk() - throws Exception { - - this.mvc.perform(get("/.well-known/jwks.json")) - .andExpect(status().isOk()); - } - -} diff --git a/samples/boot/oauth2login-webflux/README.adoc b/samples/boot/oauth2login-webflux/README.adoc deleted file mode 100644 index a96fec395b..0000000000 --- a/samples/boot/oauth2login-webflux/README.adoc +++ /dev/null @@ -1,324 +0,0 @@ -NOTE: Spring Security Reactive OAuth only supports authentication using a user info endpoint. -Support for JWT validation will be added in https://github.com/spring-projects/spring-security/issues/5330[gh-5330]. - -= OAuth 2.0 Login Sample - -This guide provides instructions on setting up the sample application with OAuth 2.0 Login using an OAuth 2.0 Provider or OpenID Connect 1.0 Provider. -The sample application uses Spring Boot 2.0.0.M6 and the `spring-security-oauth2-client` module which is new in Spring Security 5.0. - -The following sections provide detailed steps for setting up OAuth 2.0 Login for these Providers: - -* <> -* <> -* <> -* <> - -[[google-login]] -== Login with Google - -This section shows how to configure the sample application using Google as the Authentication Provider and covers the following topics: - -* <> -* <> -* <> -* <> - -[[google-initial-setup]] -=== Initial setup - -To use Google's OAuth 2.0 authentication system for login, you must set up a project in the Google API Console to obtain OAuth 2.0 credentials. - -NOTE: https://developers.google.com/identity/protocols/OpenIDConnect[Google's OAuth 2.0 implementation] for authentication conforms to the - https://openid.net/connect/[OpenID Connect 1.0] specification and is https://openid.net/certification/[OpenID Certified]. - -Follow the instructions on the https://developers.google.com/identity/protocols/OpenIDConnect[OpenID Connect] page, starting in the section, "Setting up OAuth 2.0". - -After completing the "Obtain OAuth 2.0 credentials" instructions, you should have a new OAuth Client with credentials consisting of a Client ID and a Client Secret. - -[[google-redirect-uri]] -=== Setting the redirect URI - -The redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Google -and have granted access to the OAuth Client _(created in the previous step)_ on the Consent page. - -In the "Set a redirect URI" sub-section, ensure that the *Authorized redirect URIs* field is set to `http://localhost:8080/login/oauth2/code/google`. - -TIP: The default redirect URI template is `{baseUrl}/login/oauth2/code/{registrationId}`. - The *_registrationId_* is a unique identifier for the `ClientRegistration`. - -IMPORTANT: If the application is running behind a proxy server, it is recommended to check https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#appendix-proxy-server[Proxy Server Configuration] to ensure the application is correctly configured. -Also, see the supported https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#oauth2Client-auth-code-redirect-uri[`URI` template variables] for `redirect-uri`. - -[[google-application-config]] -=== Configure application.yml - -Now that you have a new OAuth Client with Google, you need to configure the application to use the OAuth Client for the _authentication flow_. To do so: - -. Go to `application.yml` and set the following configuration: -+ -[source,yaml] ----- -spring: - security: - oauth2: - client: - registration: <1> - google: <2> - client-id: google-client-id - client-secret: google-client-secret ----- -+ -.OAuth Client properties -==== -<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties. -<2> Following the base property prefix is the ID for the `ClientRegistration`, such as google. -==== - -. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials you created earlier. - -[[google-boot-application]] -=== Boot up the application - -Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`. -You are then redirected to the default _auto-generated_ login page, which displays a link for Google. - -Click on the Google link, and you are then redirected to Google for authentication. - -After authenticating with your Google account credentials, the next page presented to you is the Consent screen. -The Consent screen asks you to either allow or deny access to the OAuth Client you created earlier. -Click *Allow* to authorize the OAuth Client to access your email address and basic profile information. - -At this point, the OAuth Client retrieves your email address and basic profile information -from the https://openid.net/specs/openid-connect-core-1_0.html#UserInfo[UserInfo Endpoint] and establishes an authenticated session. - -[[github-login]] -== Login with GitHub - -This section shows how to configure the sample application using GitHub as the Authentication Provider and covers the following topics: - -* <> -* <> -* <> - -[[github-register-application]] -=== Register OAuth application - -To use GitHub's OAuth 2.0 authentication system for login, you must https://github.com/settings/applications/new[Register a new OAuth application]. - -When registering the OAuth application, ensure the *Authorization callback URL* is set to `http://localhost:8080/login/oauth2/code/github`. - -The Authorization callback URL (redirect URI) is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with GitHub -and have granted access to the OAuth application on the _Authorize application_ page. - -TIP: The default redirect URI template is `{baseUrl}/login/oauth2/code/{registrationId}`. - The *_registrationId_* is a unique identifier for the `ClientRegistration`. - -IMPORTANT: If the application is running behind a proxy server, it is recommended to check https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#appendix-proxy-server[Proxy Server Configuration] to ensure the application is correctly configured. -Also, see the supported https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#oauth2Client-auth-code-redirect-uri[`URI` template variables] for `redirect-uri`. - -[[github-application-config]] -=== Configure application.yml - -Now that you have a new OAuth application with GitHub, you need to configure the application to use the OAuth application for the _authentication flow_. To do so: - -. Go to `application.yml` and set the following configuration: -+ -[source,yaml] ----- -spring: - security: - oauth2: - client: - registration: <1> - github: <2> - client-id: github-client-id - client-secret: github-client-secret ----- -+ -.OAuth Client properties -==== -<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties. -<2> Following the base property prefix is the ID for the `ClientRegistration`, such as github. -==== - -. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials you created earlier. - -[[github-boot-application]] -=== Boot up the application - -Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`. -You are then redirected to the default _auto-generated_ login page, which displays a link for GitHub. - -Click on the GitHub link, and you are then redirected to GitHub for authentication. - -After authenticating with your GitHub credentials, the next page presented to you is "Authorize application". -This page will ask you to *Authorize* the application you created in the previous step. -Click _Authorize application_ to allow the OAuth application to access your personal user data information. - -At this point, the OAuth Client retrieves your personal user information -from the UserInfo Endpoint and establishes an authenticated session. - -[TIP] -For detailed information returned from the UserInfo Endpoint, see the API documentation -for https://developer.github.com/v3/users/#get-the-authenticated-user["Get the authenticated user"]. - -[[facebook-login]] -== Login with Facebook - -This section shows how to configure the sample application using Facebook as the Authentication Provider and covers the following topics: - -* <> -* <> -* <> - -[[facebook-register-application]] -=== Add a New App - -To use Facebook's OAuth 2.0 authentication system for login, you must first https://developers.facebook.com/apps[Add a New App]. - -Select "Create a New App" and then the "Create a New App ID" page is presented. Enter the Display Name, Contact Email, Category and then click "Create App ID". - -NOTE: The selection for the _Category_ field is not relevant but it's a required field - select "Local". - -The next page presented is "Product Setup". Click the "Get Started" button for the *Facebook Login* product. -In the left sidebar, under _Products -> Facebook Login_, select _Settings_. - -For the field *Valid OAuth redirect URIs*, enter `http://localhost:8080/login/oauth2/code/facebook` then click _Save Changes_. - -The OAuth redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Facebook -and have granted access to the application on the _Authorize application_ page. - -TIP: The default redirect URI template is `{baseUrl}/login/oauth2/code/{registrationId}`. - The *_registrationId_* is a unique identifier for the `ClientRegistration`. - -IMPORTANT: If the application is running behind a proxy server, it is recommended to check https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#appendix-proxy-server[Proxy Server Configuration] to ensure the application is correctly configured. -Also, see the supported https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#oauth2Client-auth-code-redirect-uri[`URI` template variables] for `redirect-uri`. - -[[facebook-application-config]] -=== Configure application.yml - -Now that you have created a new application with Facebook, you need to configure the sample application to use the application for the _authentication flow_. To do so: - -. Go to `application.yml` and set the following configuration: -+ -[source,yaml] ----- -spring: - security: - oauth2: - client: - registration: <1> - facebook: <2> - client-id: facebook-client-id - client-secret: facebook-client-secret ----- -+ -.OAuth Client properties -==== -<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties. -<2> Following the base property prefix is the ID for the `ClientRegistration`, such as facebook. -==== - -. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials you created earlier. - -[[facebook-boot-application]] -=== Boot up the application - -Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`. -You are then redirected to the default _auto-generated_ login page, which displays a link for Facebook. - -Click on the Facebook link, and you are then redirected to Facebook for authentication. - -After authenticating with your Facebook credentials, the next page presented to you is "Authorize application". -This page will ask you to *Authorize* the application you created in the previous step. -Click _Authorize application_ to allow the OAuth application to access your _public profile_ and _email address_ information. - -At this point, the OAuth Client retrieves your personal user information -from the UserInfo Endpoint and establishes an authenticated session. - -[[okta-login]] -== Login with Okta - -This section shows how to configure the sample application using Okta as the Authentication Provider and covers the following topics: - -* <> -* <> -* <> -* <> - -[[okta-register-application]] -=== Add Application - -To use Okta's OAuth 2.0 authentication system for login, you must first https://www.okta.com/developer/signup[create a developer account]. - -Sign in to your account sub-domain and navigate to _Applications -> Applications_ and then select the "Add Application" button. -From the "Add Application" page, select the "Create New App" button and enter the following: - -* *Platform:* Web -* *Sign on method:* OpenID Connect - -Select the _Create_ button. -On the "General Settings" page, enter the Application Name (for example, "Spring Security Okta Login") and then select the _Next_ button. -On the "Configure OpenID Connect" page, enter `http://localhost:8080/login/oauth2/code/okta` for the field *Redirect URIs* and then select _Finish_. - -The redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Okta -and have granted access to the application on the _Authorize application_ page. - -TIP: The default redirect URI template is `{baseUrl}/login/oauth2/code/{registrationId}`. - The *_registrationId_* is a unique identifier for the `ClientRegistration`. - -IMPORTANT: If the application is running behind a proxy server, it is recommended to check https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#appendix-proxy-server[Proxy Server Configuration] to ensure the application is correctly configured. -Also, see the supported https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#oauth2Client-auth-code-redirect-uri[`URI` template variables] for `redirect-uri`. - -[[okta-assign-application-people]] -=== Assign Application to People - -From the "General" tab of the application, select the "Assignments" tab and then select the _Assign_ button. -Select _Assign to People_ and assign your account to the application. Then select the _Save and Go Back_ button. - -[[okta-application-config]] -=== Configure application.yml - -Now that you have created a new application with Okta, you need to configure the sample application to use the application for the _authentication flow_. To do so: - -. Go to `application.yml` and set the following configuration: -+ -[source,yaml] ----- -spring: - security: - oauth2: - client: - registration: <1> - okta: <2> - client-id: okta-client-id - client-secret: okta-client-secret - provider: <3> - okta: - authorization-uri: https://your-subdomain.oktapreview.com/oauth2/v1/authorize - token-uri: https://your-subdomain.oktapreview.com/oauth2/v1/token - user-info-uri: https://your-subdomain.oktapreview.com/oauth2/v1/userinfo - user-name-attribute: sub - jwk-set-uri: https://your-subdomain.oktapreview.com/oauth2/v1/keys ----- -+ -.OAuth Client properties -==== -<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties. -<2> Following the base property prefix is the ID for the `ClientRegistration`, such as okta. -<3> `spring.security.oauth2.client.provider` is the base property prefix for OAuth Provider properties. -==== - -. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials you created earlier. -As well, replace `https://your-subdomain.oktapreview.com` in `authorization-uri`, `token-uri`, `user-info-uri` and `jwk-set-uri` with the sub-domain assigned to your account during the registration process. - -[[okta-boot-application]] -=== Boot up the application - -Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`. -You are then redirected to the default _auto-generated_ login page, which displays a link for Okta. - -Click on the Okta link, and you are then redirected to Okta for authentication. - -After authenticating with your Okta account credentials, the OAuth Client retrieves your email address and basic profile information -from the https://openid.net/specs/openid-connect-core-1_0.html#UserInfo[UserInfo Endpoint] and establishes an authenticated session. diff --git a/samples/boot/oauth2login-webflux/spring-security-samples-boot-oauth2login-webflux.gradle b/samples/boot/oauth2login-webflux/spring-security-samples-boot-oauth2login-webflux.gradle deleted file mode 100644 index 49099dbd7a..0000000000 --- a/samples/boot/oauth2login-webflux/spring-security-samples-boot-oauth2login-webflux.gradle +++ /dev/null @@ -1,14 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-oauth2-client') - compile project(':spring-security-oauth2-jose') - compile 'org.springframework.boot:spring-boot-starter-thymeleaf' - compile 'org.springframework.boot:spring-boot-starter-webflux' - compile 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' - - testCompile project(':spring-security-test') - testCompile 'net.sourceforge.htmlunit:htmlunit' - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/oauth2login-webflux/src/integration-test/java/sample/OAuth2LoginApplicationTests.java b/samples/boot/oauth2login-webflux/src/integration-test/java/sample/OAuth2LoginApplicationTests.java deleted file mode 100644 index c3e2b63af6..0000000000 --- a/samples/boot/oauth2login-webflux/src/integration-test/java/sample/OAuth2LoginApplicationTests.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; - -import static org.hamcrest.core.StringContains.containsString; -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockOAuth2Login; - -/** - * Tests for {@link ReactiveOAuth2LoginApplication} - */ -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureWebTestClient -public class OAuth2LoginApplicationTests { - - @Autowired - WebTestClient test; - - @Autowired - ReactiveClientRegistrationRepository clientRegistrationRepository; - - @Test - public void requestWhenMockOidcLoginThenIndex() { - this.clientRegistrationRepository.findByRegistrationId("github") - .map((clientRegistration) -> - this.test.mutateWith(mockOAuth2Login().clientRegistration(clientRegistration)) - .get().uri("/") - .exchange() - .expectBody(String.class).value(containsString("GitHub")) - ).block(); - } -} diff --git a/samples/boot/oauth2login-webflux/src/main/java/sample/ReactiveOAuth2LoginApplication.java b/samples/boot/oauth2login-webflux/src/main/java/sample/ReactiveOAuth2LoginApplication.java deleted file mode 100644 index f6fd94e849..0000000000 --- a/samples/boot/oauth2login-webflux/src/main/java/sample/ReactiveOAuth2LoginApplication.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Rob Winch - */ -@SpringBootApplication -public class ReactiveOAuth2LoginApplication { - - public static void main(String[] args) { - SpringApplication.run(ReactiveOAuth2LoginApplication.class, args); - } - -} diff --git a/samples/boot/oauth2login-webflux/src/main/java/sample/web/OAuth2LoginController.java b/samples/boot/oauth2login-webflux/src/main/java/sample/web/OAuth2LoginController.java deleted file mode 100644 index 2e03a6adcd..0000000000 --- a/samples/boot/oauth2login-webflux/src/main/java/sample/web/OAuth2LoginController.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.web; - -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; -import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient; -import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; - -/** - * @author Rob Winch - */ -@Controller -public class OAuth2LoginController { - - @GetMapping("/") - public String index(Model model, - @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient, - @AuthenticationPrincipal OAuth2User oauth2User) { - model.addAttribute("userName", oauth2User.getName()); - model.addAttribute("clientName", authorizedClient.getClientRegistration().getClientName()); - model.addAttribute("userAttributes", oauth2User.getAttributes()); - return "index"; - } -} diff --git a/samples/boot/oauth2login-webflux/src/main/resources/application.yml b/samples/boot/oauth2login-webflux/src/main/resources/application.yml deleted file mode 100644 index 73b08fbd83..0000000000 --- a/samples/boot/oauth2login-webflux/src/main/resources/application.yml +++ /dev/null @@ -1,35 +0,0 @@ -server: - port: 8080 - -logging: - level: - root: INFO - org.springframework.web: INFO - org.springframework.security: INFO -# org.springframework.boot.autoconfigure: DEBUG - -spring: - thymeleaf: - cache: false - security: - oauth2: - client: - registration: - google: - client-id: your-app-client-id - client-secret: your-app-client-secret - github: - client-id: your-app-client-id - client-secret: your-app-client-secret - facebook: - client-id: your-app-client-id - client-secret: your-app-client-secret - okta: - client-id: your-app-client-id - client-secret: your-app-client-secret - provider: - okta: - authorization-uri: https://your-subdomain.oktapreview.com/oauth2/v1/authorize - token-uri: https://your-subdomain.oktapreview.com/oauth2/v1/token - user-info-uri: https://your-subdomain.oktapreview.com/oauth2/v1/userinfo - jwk-set-uri: https://your-subdomain.oktapreview.com/oauth2/v1/keys diff --git a/samples/boot/oauth2login-webflux/src/main/resources/templates/index.html b/samples/boot/oauth2login-webflux/src/main/resources/templates/index.html deleted file mode 100644 index ce8cdcde23..0000000000 --- a/samples/boot/oauth2login-webflux/src/main/resources/templates/index.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - Spring Security - OAuth 2.0 Login - - - -
-
- User: -
-
 
-
- Log Out -
-
-

OAuth 2.0 Login with Spring Security

-
- You are successfully logged in - via the OAuth 2.0 Client -
-
 
-
- User Attributes: -
    -
  • - : -
  • -
-
- - diff --git a/samples/boot/oauth2login-webflux/src/test/java/sample/OAuth2LoginControllerTests.java b/samples/boot/oauth2login-webflux/src/test/java/sample/OAuth2LoginControllerTests.java deleted file mode 100644 index 11ae5f8ba6..0000000000 --- a/samples/boot/oauth2login-webflux/src/test/java/sample/OAuth2LoginControllerTests.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import sample.web.OAuth2LoginController; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; -import org.springframework.core.ReactiveAdapterRegistry; -import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; -import org.springframework.security.oauth2.client.web.reactive.result.method.annotation.OAuth2AuthorizedClientArgumentResolver; -import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; -import org.springframework.security.web.reactive.result.method.annotation.AuthenticationPrincipalArgumentResolver; -import org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; -import org.springframework.web.reactive.result.view.ViewResolver; - -import static org.hamcrest.Matchers.containsString; -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockOAuth2Login; -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity; - -/** - * @author Josh Cummings - */ -@RunWith(SpringRunner.class) -@WebFluxTest(OAuth2LoginController.class) -public class OAuth2LoginControllerTests { - - @Autowired - OAuth2LoginController controller; - - @Autowired - ViewResolver viewResolver; - - @Mock - ReactiveClientRegistrationRepository clientRegistrationRepository; - - @Mock - ServerOAuth2AuthorizedClientRepository authorizedClientRepository; - - WebTestClient rest; - - @Before - public void setup() { - this.rest = WebTestClient - .bindToController(this.controller) - .apply(springSecurity()) - .webFilter(new SecurityContextServerWebExchangeWebFilter()) - .argumentResolvers((c) -> { - c.addCustomResolver(new AuthenticationPrincipalArgumentResolver(new ReactiveAdapterRegistry())); - c.addCustomResolver(new OAuth2AuthorizedClientArgumentResolver - (this.clientRegistrationRepository, this.authorizedClientRepository)); - }) - .viewResolvers((c) -> c.viewResolver(this.viewResolver)) - .build(); - } - - @Test - public void indexGreetsAuthenticatedUser() { - this.rest.mutateWith(mockOAuth2Login()) - .get().uri("/").exchange() - .expectBody(String.class).value(containsString("user")); - } -} diff --git a/samples/boot/oauth2login/README.adoc b/samples/boot/oauth2login/README.adoc deleted file mode 100644 index e949a7f84e..0000000000 --- a/samples/boot/oauth2login/README.adoc +++ /dev/null @@ -1,321 +0,0 @@ -= OAuth 2.0 Login Sample - -This guide provides instructions on setting up the sample application with OAuth 2.0 Login using an OAuth 2.0 Provider or OpenID Connect 1.0 Provider. -The sample application uses Spring Boot 2.0.0.M6 and the `spring-security-oauth2-client` module which is new in Spring Security 5.0. - -The following sections provide detailed steps for setting up OAuth 2.0 Login for these Providers: - -* <> -* <> -* <> -* <> - -[[google-login]] -== Login with Google - -This section shows how to configure the sample application using Google as the Authentication Provider and covers the following topics: - -* <> -* <> -* <> -* <> - -[[google-initial-setup]] -=== Initial setup - -To use Google's OAuth 2.0 authentication system for login, you must set up a project in the Google API Console to obtain OAuth 2.0 credentials. - -NOTE: https://developers.google.com/identity/protocols/OpenIDConnect[Google's OAuth 2.0 implementation] for authentication conforms to the - https://openid.net/connect/[OpenID Connect 1.0] specification and is https://openid.net/certification/[OpenID Certified]. - -Follow the instructions on the https://developers.google.com/identity/protocols/OpenIDConnect[OpenID Connect] page, starting in the section, "Setting up OAuth 2.0". - -After completing the "Obtain OAuth 2.0 credentials" instructions, you should have a new OAuth Client with credentials consisting of a Client ID and a Client Secret. - -[[google-redirect-uri]] -=== Setting the redirect URI - -The redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Google -and have granted access to the OAuth Client _(created in the previous step)_ on the Consent page. - -In the "Set a redirect URI" sub-section, ensure that the *Authorized redirect URIs* field is set to `http://localhost:8080/login/oauth2/code/google`. - -TIP: The default redirect URI template is `{baseUrl}/login/oauth2/code/{registrationId}`. - The *_registrationId_* is a unique identifier for the `ClientRegistration`. - -IMPORTANT: If the application is running behind a proxy server, it is recommended to check https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#appendix-proxy-server[Proxy Server Configuration] to ensure the application is correctly configured. -Also, see the supported https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#oauth2Client-auth-code-redirect-uri[`URI` template variables] for `redirect-uri`. - -[[google-application-config]] -=== Configure application.yml - -Now that you have a new OAuth Client with Google, you need to configure the application to use the OAuth Client for the _authentication flow_. To do so: - -. Go to `application.yml` and set the following configuration: -+ -[source,yaml] ----- -spring: - security: - oauth2: - client: - registration: <1> - google: <2> - client-id: google-client-id - client-secret: google-client-secret ----- -+ -.OAuth Client properties -==== -<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties. -<2> Following the base property prefix is the ID for the `ClientRegistration`, such as google. -==== - -. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials you created earlier. - -[[google-boot-application]] -=== Boot up the application - -Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`. -You are then redirected to the default _auto-generated_ login page, which displays a link for Google. - -Click on the Google link, and you are then redirected to Google for authentication. - -After authenticating with your Google account credentials, the next page presented to you is the Consent screen. -The Consent screen asks you to either allow or deny access to the OAuth Client you created earlier. -Click *Allow* to authorize the OAuth Client to access your email address and basic profile information. - -At this point, the OAuth Client retrieves your email address and basic profile information -from the https://openid.net/specs/openid-connect-core-1_0.html#UserInfo[UserInfo Endpoint] and establishes an authenticated session. - -[[github-login]] -== Login with GitHub - -This section shows how to configure the sample application using GitHub as the Authentication Provider and covers the following topics: - -* <> -* <> -* <> - -[[github-register-application]] -=== Register OAuth application - -To use GitHub's OAuth 2.0 authentication system for login, you must https://github.com/settings/applications/new[Register a new OAuth application]. - -When registering the OAuth application, ensure the *Authorization callback URL* is set to `http://localhost:8080/login/oauth2/code/github`. - -The Authorization callback URL (redirect URI) is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with GitHub -and have granted access to the OAuth application on the _Authorize application_ page. - -TIP: The default redirect URI template is `{baseUrl}/login/oauth2/code/{registrationId}`. - The *_registrationId_* is a unique identifier for the `ClientRegistration`. - -IMPORTANT: If the application is running behind a proxy server, it is recommended to check https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#appendix-proxy-server[Proxy Server Configuration] to ensure the application is correctly configured. -Also, see the supported https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#oauth2Client-auth-code-redirect-uri[`URI` template variables] for `redirect-uri`. - -[[github-application-config]] -=== Configure application.yml - -Now that you have a new OAuth application with GitHub, you need to configure the application to use the OAuth application for the _authentication flow_. To do so: - -. Go to `application.yml` and set the following configuration: -+ -[source,yaml] ----- -spring: - security: - oauth2: - client: - registration: <1> - github: <2> - client-id: github-client-id - client-secret: github-client-secret ----- -+ -.OAuth Client properties -==== -<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties. -<2> Following the base property prefix is the ID for the `ClientRegistration`, such as github. -==== - -. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials you created earlier. - -[[github-boot-application]] -=== Boot up the application - -Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`. -You are then redirected to the default _auto-generated_ login page, which displays a link for GitHub. - -Click on the GitHub link, and you are then redirected to GitHub for authentication. - -After authenticating with your GitHub credentials, the next page presented to you is "Authorize application". -This page will ask you to *Authorize* the application you created in the previous step. -Click _Authorize application_ to allow the OAuth application to access your personal user data information. - -At this point, the OAuth Client retrieves your personal user information -from the UserInfo Endpoint and establishes an authenticated session. - -[TIP] -For detailed information returned from the UserInfo Endpoint, see the API documentation -for https://developer.github.com/v3/users/#get-the-authenticated-user["Get the authenticated user"]. - -[[facebook-login]] -== Login with Facebook - -This section shows how to configure the sample application using Facebook as the Authentication Provider and covers the following topics: - -* <> -* <> -* <> - -[[facebook-register-application]] -=== Add a New App - -To use Facebook's OAuth 2.0 authentication system for login, you must first https://developers.facebook.com/apps[Add a New App]. - -Select "Create a New App" and then the "Create a New App ID" page is presented. Enter the Display Name, Contact Email, Category and then click "Create App ID". - -NOTE: The selection for the _Category_ field is not relevant but it's a required field - select "Local". - -The next page presented is "Product Setup". Click the "Get Started" button for the *Facebook Login* product. -In the left sidebar, under _Products -> Facebook Login_, select _Settings_. - -For the field *Valid OAuth redirect URIs*, enter `http://localhost:8080/login/oauth2/code/facebook` then click _Save Changes_. - -The OAuth redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Facebook -and have granted access to the application on the _Authorize application_ page. - -TIP: The default redirect URI template is `{baseUrl}/login/oauth2/code/{registrationId}`. - The *_registrationId_* is a unique identifier for the `ClientRegistration`. - -IMPORTANT: If the application is running behind a proxy server, it is recommended to check https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#appendix-proxy-server[Proxy Server Configuration] to ensure the application is correctly configured. -Also, see the supported https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#oauth2Client-auth-code-redirect-uri[`URI` template variables] for `redirect-uri`. - -[[facebook-application-config]] -=== Configure application.yml - -Now that you have created a new application with Facebook, you need to configure the sample application to use the application for the _authentication flow_. To do so: - -. Go to `application.yml` and set the following configuration: -+ -[source,yaml] ----- -spring: - security: - oauth2: - client: - registration: <1> - facebook: <2> - client-id: facebook-client-id - client-secret: facebook-client-secret ----- -+ -.OAuth Client properties -==== -<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties. -<2> Following the base property prefix is the ID for the `ClientRegistration`, such as facebook. -==== - -. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials you created earlier. - -[[facebook-boot-application]] -=== Boot up the application - -Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`. -You are then redirected to the default _auto-generated_ login page, which displays a link for Facebook. - -Click on the Facebook link, and you are then redirected to Facebook for authentication. - -After authenticating with your Facebook credentials, the next page presented to you is "Authorize application". -This page will ask you to *Authorize* the application you created in the previous step. -Click _Authorize application_ to allow the OAuth application to access your _public profile_ and _email address_ information. - -At this point, the OAuth Client retrieves your personal user information -from the UserInfo Endpoint and establishes an authenticated session. - -[[okta-login]] -== Login with Okta - -This section shows how to configure the sample application using Okta as the Authentication Provider and covers the following topics: - -* <> -* <> -* <> -* <> - -[[okta-register-application]] -=== Add Application - -To use Okta's OAuth 2.0 authentication system for login, you must first https://www.okta.com/developer/signup[create a developer account]. - -Sign in to your account sub-domain and navigate to _Applications -> Applications_ and then select the "Add Application" button. -From the "Add Application" page, select the "Create New App" button and enter the following: - -* *Platform:* Web -* *Sign on method:* OpenID Connect - -Select the _Create_ button. -On the "General Settings" page, enter the Application Name (for example, "Spring Security Okta Login") and then select the _Next_ button. -On the "Configure OpenID Connect" page, enter `http://localhost:8080/login/oauth2/code/okta` for the field *Redirect URIs* and then select _Finish_. - -The redirect URI is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with Okta -and have granted access to the application on the _Authorize application_ page. - -TIP: The default redirect URI template is `{baseUrl}/login/oauth2/code/{registrationId}`. - The *_registrationId_* is a unique identifier for the `ClientRegistration`. - -IMPORTANT: If the application is running behind a proxy server, it is recommended to check https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#appendix-proxy-server[Proxy Server Configuration] to ensure the application is correctly configured. -Also, see the supported https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#oauth2Client-auth-code-redirect-uri[`URI` template variables] for `redirect-uri`. - -[[okta-assign-application-people]] -=== Assign Application to People - -From the "General" tab of the application, select the "Assignments" tab and then select the _Assign_ button. -Select _Assign to People_ and assign your account to the application. Then select the _Save and Go Back_ button. - -[[okta-application-config]] -=== Configure application.yml - -Now that you have created a new application with Okta, you need to configure the sample application to use the application for the _authentication flow_. To do so: - -. Go to `application.yml` and set the following configuration: -+ -[source,yaml] ----- -spring: - security: - oauth2: - client: - registration: <1> - okta: <2> - client-id: okta-client-id - client-secret: okta-client-secret - provider: <3> - okta: - authorization-uri: https://your-subdomain.oktapreview.com/oauth2/v1/authorize - token-uri: https://your-subdomain.oktapreview.com/oauth2/v1/token - user-info-uri: https://your-subdomain.oktapreview.com/oauth2/v1/userinfo - user-name-attribute: sub - jwk-set-uri: https://your-subdomain.oktapreview.com/oauth2/v1/keys ----- -+ -.OAuth Client properties -==== -<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties. -<2> Following the base property prefix is the ID for the `ClientRegistration`, such as okta. -<3> `spring.security.oauth2.client.provider` is the base property prefix for OAuth Provider properties. -==== - -. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials you created earlier. -As well, replace `https://your-subdomain.oktapreview.com` in `authorization-uri`, `token-uri`, `user-info-uri` and `jwk-set-uri` with the sub-domain assigned to your account during the registration process. - -[[okta-boot-application]] -=== Boot up the application - -Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`. -You are then redirected to the default _auto-generated_ login page, which displays a link for Okta. - -Click on the Okta link, and you are then redirected to Okta for authentication. - -After authenticating with your Okta account credentials, the OAuth Client retrieves your email address and basic profile information -from the https://openid.net/specs/openid-connect-core-1_0.html#UserInfo[UserInfo Endpoint] and establishes an authenticated session. diff --git a/samples/boot/oauth2login/spring-security-samples-boot-oauth2login.gradle b/samples/boot/oauth2login/spring-security-samples-boot-oauth2login.gradle deleted file mode 100644 index ef3a4e27b5..0000000000 --- a/samples/boot/oauth2login/spring-security-samples-boot-oauth2login.gradle +++ /dev/null @@ -1,14 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-oauth2-client') - compile project(':spring-security-oauth2-jose') - compile 'org.springframework.boot:spring-boot-starter-thymeleaf' - compile 'org.springframework.boot:spring-boot-starter-web' - compile 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' - - testCompile project(':spring-security-test') - testCompile 'net.sourceforge.htmlunit:htmlunit' - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/oauth2login/src/integration-test/java/sample/OAuth2LoginApplicationTests.java b/samples/boot/oauth2login/src/integration-test/java/sample/OAuth2LoginApplicationTests.java deleted file mode 100644 index 77867dbbc8..0000000000 --- a/samples/boot/oauth2login/src/integration-test/java/sample/OAuth2LoginApplicationTests.java +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import java.net.URI; -import java.net.URL; -import java.net.URLDecoder; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - -import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; -import com.gargoylesoftware.htmlunit.WebClient; -import com.gargoylesoftware.htmlunit.WebResponse; -import com.gargoylesoftware.htmlunit.html.DomNodeList; -import com.gargoylesoftware.htmlunit.html.HtmlAnchor; -import com.gargoylesoftware.htmlunit.html.HtmlElement; -import com.gargoylesoftware.htmlunit.html.HtmlPage; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -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.TestConfiguration; -import org.springframework.http.HttpStatus; -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.WebSecurityConfigurerAdapter; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient; -import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; -import org.springframework.security.oauth2.client.registration.ClientRegistration; -import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; -import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; -import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; -import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter; -import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter; -import org.springframework.security.oauth2.core.OAuth2AccessToken; -import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; -import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationResponseType; -import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; -import org.springframework.security.oauth2.core.user.DefaultOAuth2User; -import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.security.oauth2.core.user.OAuth2UserAuthority; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.web.util.UriComponents; -import org.springframework.web.util.UriComponentsBuilder; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.oauth2Login; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; - -/** - * Integration tests for the OAuth 2.0 client filters {@link OAuth2AuthorizationRequestRedirectFilter} - * and {@link OAuth2LoginAuthenticationFilter}. These filters work together to realize - * OAuth 2.0 Login leveraging the Authorization Code Grant flow. - * - * @author Joe Grandja - * @since 5.0 - */ -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -public class OAuth2LoginApplicationTests { - private static final String AUTHORIZATION_BASE_URI = "/oauth2/authorization"; - private static final String AUTHORIZE_BASE_URL = "http://localhost:8080/login/oauth2/code"; - - @Autowired - private WebClient webClient; - - @Autowired - private MockMvc mvc; - - @Autowired - private ClientRegistrationRepository clientRegistrationRepository; - - @Before - public void setup() { - this.webClient.getCookieManager().clearCookies(); - } - - @Test - public void requestIndexPageWhenNotAuthenticatedThenDisplayLoginPage() throws Exception { - HtmlPage page = this.webClient.getPage("/"); - this.assertLoginPage(page); - } - - @Test - public void requestOtherPageWhenNotAuthenticatedThenDisplayLoginPage() throws Exception { - HtmlPage page = this.webClient.getPage("/other-page"); - this.assertLoginPage(page); - } - - @Test - public void requestAuthorizeGitHubClientWhenLinkClickedThenStatusRedirectForAuthorization() throws Exception { - HtmlPage page = this.webClient.getPage("/"); - - ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("github"); - - HtmlAnchor clientAnchorElement = this.getClientAnchorElement(page, clientRegistration); - assertThat(clientAnchorElement).isNotNull(); - - WebResponse response = this.followLinkDisableRedirects(clientAnchorElement); - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.MOVED_PERMANENTLY.value()); - - String authorizeRedirectUri = response.getResponseHeaderValue("Location"); - assertThat(authorizeRedirectUri).isNotNull(); - - UriComponents uriComponents = UriComponentsBuilder.fromUri(URI.create(authorizeRedirectUri)).build(); - - String requestUri = uriComponents.getScheme() + "://" + uriComponents.getHost() + uriComponents.getPath(); - assertThat(requestUri).isEqualTo(clientRegistration.getProviderDetails().getAuthorizationUri()); - - Map params = uriComponents.getQueryParams().toSingleValueMap(); - - assertThat(params.get(OAuth2ParameterNames.RESPONSE_TYPE)).isEqualTo(OAuth2AuthorizationResponseType.CODE.getValue()); - assertThat(params.get(OAuth2ParameterNames.CLIENT_ID)).isEqualTo(clientRegistration.getClientId()); - String redirectUri = AUTHORIZE_BASE_URL + "/" + clientRegistration.getRegistrationId(); - assertThat(URLDecoder.decode(params.get(OAuth2ParameterNames.REDIRECT_URI), "UTF-8")).isEqualTo(redirectUri); - assertThat(URLDecoder.decode(params.get(OAuth2ParameterNames.SCOPE), "UTF-8")) - .isEqualTo(clientRegistration.getScopes().stream().collect(Collectors.joining(" "))); - assertThat(params.get(OAuth2ParameterNames.STATE)).isNotNull(); - } - - @Test - public void requestAuthorizeClientWhenInvalidClientThenStatusInternalServerError() throws Exception { - HtmlPage page = this.webClient.getPage("/"); - - ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("google"); - - HtmlAnchor clientAnchorElement = this.getClientAnchorElement(page, clientRegistration); - assertThat(clientAnchorElement).isNotNull(); - clientAnchorElement.setAttribute("href", clientAnchorElement.getHrefAttribute() + "-invalid"); - - WebResponse response = null; - try { - clientAnchorElement.click(); - } catch (FailingHttpStatusCodeException ex) { - response = ex.getResponse(); - } - - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR.value()); - } - - @Test - public void requestAuthorizationCodeGrantWhenValidAuthorizationResponseThenDisplayIndexPage() throws Exception { - HtmlPage page = this.webClient.getPage("/"); - - ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("github"); - - HtmlAnchor clientAnchorElement = this.getClientAnchorElement(page, clientRegistration); - assertThat(clientAnchorElement).isNotNull(); - - WebResponse response = this.followLinkDisableRedirects(clientAnchorElement); - - UriComponents authorizeRequestUriComponents = UriComponentsBuilder.fromUri( - URI.create(response.getResponseHeaderValue("Location"))).build(); - - Map params = authorizeRequestUriComponents.getQueryParams().toSingleValueMap(); - String code = "auth-code"; - String state = URLDecoder.decode(params.get(OAuth2ParameterNames.STATE), "UTF-8"); - String redirectUri = URLDecoder.decode(params.get(OAuth2ParameterNames.REDIRECT_URI), "UTF-8"); - - String authorizationResponseUri = - UriComponentsBuilder.fromHttpUrl(redirectUri) - .queryParam(OAuth2ParameterNames.CODE, code) - .queryParam(OAuth2ParameterNames.STATE, state) - .build().encode().toUriString(); - - page = this.webClient.getPage(new URL(authorizationResponseUri)); - this.assertIndexPage(page); - } - - @Test - public void requestAuthorizationCodeGrantWhenNoMatchingAuthorizationRequestThenDisplayLoginPageWithError() throws Exception { - HtmlPage page = this.webClient.getPage("/"); - URL loginPageUrl = page.getBaseURL(); - URL loginErrorPageUrl = new URL(loginPageUrl.toString() + "?error"); - - ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("google"); - - String code = "auth-code"; - String state = "state"; - String redirectUri = AUTHORIZE_BASE_URL + "/" + clientRegistration.getRegistrationId(); - - String authorizationResponseUri = - UriComponentsBuilder.fromHttpUrl(redirectUri) - .queryParam(OAuth2ParameterNames.CODE, code) - .queryParam(OAuth2ParameterNames.STATE, state) - .build().encode().toUriString(); - - // Clear session cookie will ensure the 'session-saved' - // Authorization Request (from previous request) is not found - this.webClient.getCookieManager().clearCookies(); - - page = this.webClient.getPage(new URL(authorizationResponseUri)); - assertThat(page.getBaseURL()).isEqualTo(loginErrorPageUrl); - - HtmlElement errorElement = page.getBody().getFirstByXPath("div"); - assertThat(errorElement).isNotNull(); - assertThat(errorElement.asText()).contains("authorization_request_not_found"); - } - - @Test - public void requestAuthorizationCodeGrantWhenInvalidStateParamThenDisplayLoginPageWithError() throws Exception { - HtmlPage page = this.webClient.getPage("/"); - URL loginPageUrl = page.getBaseURL(); - URL loginErrorPageUrl = new URL(loginPageUrl.toString() + "?error"); - - ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("google"); - - HtmlAnchor clientAnchorElement = this.getClientAnchorElement(page, clientRegistration); - assertThat(clientAnchorElement).isNotNull(); - this.followLinkDisableRedirects(clientAnchorElement); - - String code = "auth-code"; - String state = "invalid-state"; - String redirectUri = AUTHORIZE_BASE_URL + "/" + clientRegistration.getRegistrationId(); - - String authorizationResponseUri = - UriComponentsBuilder.fromHttpUrl(redirectUri) - .queryParam(OAuth2ParameterNames.CODE, code) - .queryParam(OAuth2ParameterNames.STATE, state) - .build().encode().toUriString(); - - page = this.webClient.getPage(new URL(authorizationResponseUri)); - assertThat(page.getBaseURL()).isEqualTo(loginErrorPageUrl); - - HtmlElement errorElement = page.getBody().getFirstByXPath("div"); - assertThat(errorElement).isNotNull(); - assertThat(errorElement.asText()).contains("authorization_request_not_found"); - } - - @Test - public void requestWhenMockOAuth2LoginThenIndex() throws Exception { - ClientRegistration clientRegistration = this.clientRegistrationRepository.findByRegistrationId("github"); - this.mvc.perform(get("/").with(oauth2Login().clientRegistration(clientRegistration))) - .andExpect(model().attribute("userName", "user")) - .andExpect(model().attribute("clientName", "GitHub")) - .andExpect(model().attribute("userAttributes", Collections.singletonMap("sub", "user"))); - } - - private void assertLoginPage(HtmlPage page) { - assertThat(page.getTitleText()).isEqualTo("Please sign in"); - - int expectedClients = 4; - - List clientAnchorElements = page.getAnchors(); - assertThat(clientAnchorElements.size()).isEqualTo(expectedClients); - - ClientRegistration googleClientRegistration = this.clientRegistrationRepository.findByRegistrationId("google"); - ClientRegistration githubClientRegistration = this.clientRegistrationRepository.findByRegistrationId("github"); - ClientRegistration facebookClientRegistration = this.clientRegistrationRepository.findByRegistrationId("facebook"); - ClientRegistration oktaClientRegistration = this.clientRegistrationRepository.findByRegistrationId("okta"); - - String baseAuthorizeUri = AUTHORIZATION_BASE_URI + "/"; - String googleClientAuthorizeUri = baseAuthorizeUri + googleClientRegistration.getRegistrationId(); - String githubClientAuthorizeUri = baseAuthorizeUri + githubClientRegistration.getRegistrationId(); - String facebookClientAuthorizeUri = baseAuthorizeUri + facebookClientRegistration.getRegistrationId(); - String oktaClientAuthorizeUri = baseAuthorizeUri + oktaClientRegistration.getRegistrationId(); - - for (int i=0; i divElements = page.getBody().getElementsByTagName("div"); - assertThat(divElements.get(1).asText()).contains("User: joeg@springsecurity.io"); - assertThat(divElements.get(4).asText()).contains("You are successfully logged in joeg@springsecurity.io"); - } - - private HtmlAnchor getClientAnchorElement(HtmlPage page, ClientRegistration clientRegistration) { - Optional clientAnchorElement = page.getAnchors().stream() - .filter((e) -> e.asText().equals(clientRegistration.getClientName())).findFirst(); - - return (clientAnchorElement.orElse(null)); - } - - private WebResponse followLinkDisableRedirects(HtmlAnchor anchorElement) throws Exception { - WebResponse response = null; - try { - // Disable the automatic redirection (which will trigger - // an exception) so that we can capture the response - this.webClient.getOptions().setRedirectEnabled(false); - anchorElement.click(); - } catch (FailingHttpStatusCodeException ex) { - response = ex.getResponse(); - this.webClient.getOptions().setRedirectEnabled(true); - } - return response; - } - - @EnableWebSecurity - @TestConfiguration - public static class SecurityTestConfig extends WebSecurityConfigurerAdapter { - - // @formatter:off - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .authorizeRequests((authorizeRequests) -> - authorizeRequests - .anyRequest().authenticated() - ) - .oauth2Login((oauth2Login) -> - oauth2Login - .tokenEndpoint((tokenEndpoint) -> - tokenEndpoint - .accessTokenResponseClient(this.mockAccessTokenResponseClient()) - ) - .userInfoEndpoint((userInfoEndpoint) -> - userInfoEndpoint - .userService(this.mockUserService()) - ) - ); - } - // @formatter:on - - private OAuth2AccessTokenResponseClient mockAccessTokenResponseClient() { - OAuth2AccessTokenResponse accessTokenResponse = OAuth2AccessTokenResponse.withToken("access-token-1234") - .tokenType(OAuth2AccessToken.TokenType.BEARER) - .expiresIn(60 * 1000) - .build(); - - OAuth2AccessTokenResponseClient tokenResponseClient = mock(OAuth2AccessTokenResponseClient.class); - when(tokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); - return tokenResponseClient; - } - - private OAuth2UserService mockUserService() { - Map attributes = new HashMap<>(); - attributes.put("id", "joeg"); - attributes.put("first-name", "Joe"); - attributes.put("last-name", "Grandja"); - attributes.put("email", "joeg@springsecurity.io"); - - GrantedAuthority authority = new OAuth2UserAuthority(attributes); - Set authorities = new HashSet<>(); - authorities.add(authority); - - DefaultOAuth2User user = new DefaultOAuth2User(authorities, attributes, "email"); - - OAuth2UserService userService = mock(OAuth2UserService.class); - when(userService.loadUser(any())).thenReturn(user); - return userService; - } - } -} diff --git a/samples/boot/oauth2login/src/main/java/sample/OAuth2LoginApplication.java b/samples/boot/oauth2login/src/main/java/sample/OAuth2LoginApplication.java deleted file mode 100644 index dc69b3f9ec..0000000000 --- a/samples/boot/oauth2login/src/main/java/sample/OAuth2LoginApplication.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Joe Grandja - */ -@SpringBootApplication -public class OAuth2LoginApplication { - - public static void main(String[] args) { - SpringApplication.run(OAuth2LoginApplication.class, args); - } -} diff --git a/samples/boot/oauth2login/src/main/java/sample/web/OAuth2LoginController.java b/samples/boot/oauth2login/src/main/java/sample/web/OAuth2LoginController.java deleted file mode 100644 index fa46a60ad7..0000000000 --- a/samples/boot/oauth2login/src/main/java/sample/web/OAuth2LoginController.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.web; - -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; -import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient; -import org.springframework.security.oauth2.core.user.OAuth2User; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; - -/** - * @author Joe Grandja - * @author Rob Winch - */ -@Controller -public class OAuth2LoginController { - - @GetMapping("/") - public String index(Model model, - @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient, - @AuthenticationPrincipal OAuth2User oauth2User) { - model.addAttribute("userName", oauth2User.getName()); - model.addAttribute("clientName", authorizedClient.getClientRegistration().getClientName()); - model.addAttribute("userAttributes", oauth2User.getAttributes()); - return "index"; - } -} diff --git a/samples/boot/oauth2login/src/main/resources/application.yml b/samples/boot/oauth2login/src/main/resources/application.yml deleted file mode 100644 index 73b08fbd83..0000000000 --- a/samples/boot/oauth2login/src/main/resources/application.yml +++ /dev/null @@ -1,35 +0,0 @@ -server: - port: 8080 - -logging: - level: - root: INFO - org.springframework.web: INFO - org.springframework.security: INFO -# org.springframework.boot.autoconfigure: DEBUG - -spring: - thymeleaf: - cache: false - security: - oauth2: - client: - registration: - google: - client-id: your-app-client-id - client-secret: your-app-client-secret - github: - client-id: your-app-client-id - client-secret: your-app-client-secret - facebook: - client-id: your-app-client-id - client-secret: your-app-client-secret - okta: - client-id: your-app-client-id - client-secret: your-app-client-secret - provider: - okta: - authorization-uri: https://your-subdomain.oktapreview.com/oauth2/v1/authorize - token-uri: https://your-subdomain.oktapreview.com/oauth2/v1/token - user-info-uri: https://your-subdomain.oktapreview.com/oauth2/v1/userinfo - jwk-set-uri: https://your-subdomain.oktapreview.com/oauth2/v1/keys diff --git a/samples/boot/oauth2login/src/main/resources/templates/index.html b/samples/boot/oauth2login/src/main/resources/templates/index.html deleted file mode 100644 index 629d8ac8ee..0000000000 --- a/samples/boot/oauth2login/src/main/resources/templates/index.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - Spring Security - OAuth 2.0 Login - - - -
-
- User: -
-
 
-
-
- -
-
-
-

OAuth 2.0 Login with Spring Security

-
- You are successfully logged in - via the OAuth 2.0 Client -
-
 
-
- User Attributes: -
    -
  • - : -
  • -
-
- - diff --git a/samples/boot/oauth2login/src/test/java/sample/web/OAuth2LoginControllerTests.java b/samples/boot/oauth2login/src/test/java/sample/web/OAuth2LoginControllerTests.java deleted file mode 100644 index 6a3af42ff7..0000000000 --- a/samples/boot/oauth2login/src/test/java/sample/web/OAuth2LoginControllerTests.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.web; - -import java.util.Collections; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.security.oauth2.client.registration.ClientRegistration; -import org.springframework.security.oauth2.core.AuthorizationGrantType; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; - -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.oauth2Login; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; - -/** - * Tests for {@link OAuth2LoginController} - * - * @author Josh Cummings - */ -@RunWith(SpringRunner.class) -@WebMvcTest(OAuth2LoginController.class) -public class OAuth2LoginControllerTests { - - @Autowired - MockMvc mvc; - - @Test - public void rootWhenAuthenticatedReturnsUserAndClient() throws Exception { - this.mvc.perform(get("/").with(oauth2Login())) - .andExpect(model().attribute("userName", "user")) - .andExpect(model().attribute("clientName", "test")) - .andExpect(model().attribute("userAttributes", Collections.singletonMap("sub", "user"))); - } - - @Test - public void rootWhenOverridingClientRegistrationReturnsAccordingly() throws Exception { - ClientRegistration clientRegistration = ClientRegistration.withRegistrationId("test") - .authorizationGrantType(AuthorizationGrantType.PASSWORD) - .clientId("my-client-id") - .clientName("my-client-name") - .tokenUri("https://token-uri.example.org") - .build(); - - this.mvc.perform(get("/").with(oauth2Login() - .clientRegistration(clientRegistration) - .attributes((a) -> a.put("sub", "spring-security")))) - .andExpect(model().attribute("userName", "spring-security")) - .andExpect(model().attribute("clientName", "my-client-name")) - .andExpect(model().attribute("userAttributes", Collections.singletonMap("sub", "spring-security"))); - } -} diff --git a/samples/boot/oauth2resourceserver-jwe/README.adoc b/samples/boot/oauth2resourceserver-jwe/README.adoc deleted file mode 100644 index 84c64f6f58..0000000000 --- a/samples/boot/oauth2resourceserver-jwe/README.adoc +++ /dev/null @@ -1,119 +0,0 @@ -= OAuth 2.0 Resource Server Sample - -This sample demonstrates integrating Resource Server with a mock Authorization Server, though it can be modified to integrate -with your favorite Authorization Server. This resource server is configured to accept JWE-encrypted tokens. - -With it, you can run the integration tests or run the application as a stand-alone service to explore how you can -secure your own service with OAuth 2.0 Bearer Tokens using Spring Security. - -== 1. Running the tests - -To run the tests, do: - -```bash -./gradlew integrationTest -``` - -Or import the project into your IDE and run `OAuth2ResourceServerApplicationTests` from there. - -=== What is it doing? - -By default, the tests are pointing at a mock Authorization Server instance. - -The tests are configured with a set of hard-coded tokens originally obtained from the mock Authorization Server, -and each makes a query to the Resource Server with their corresponding token. - -The Resource Server decrypts the token and subsquently verifies it with the Authorization Server and authorizes the request, returning the phrase - -```bash -Hello, subject! -``` - -where "subject" is the value of the `sub` field in the JWT returned by the Authorization Server. - -== 2. Running the app - -To run as a stand-alone application, do: - -```bash -./gradlew bootRun -``` - -Or import the project into your IDE and run `OAuth2ResourceServerApplication` from there. - -Once it is up, you can use the following token: - -```bash -export TOKEN=eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.IyeWtsTonaiWJdoT13B0M7gpqVxAirVGlfqFI4TOmTRcVHICs_ESezS7fa0ODS9XYdwklTtG7hH39yeeMzr2Zo1Ghh-m36fdoqQrV1Do04rUvuTjqbgyNffeZEGB6rquJ-cyAVjp_Oljy10-Bbnw7CeVGwNBSVo9UCB5j49OlNWhLxFpYARFmOlYpXj-s4Q4JiqV6EvjDAYeohAR4QQmND3qoxR-s2I6SLcIho0sSSpUlhrRiqu2uvWefHDcZJdW2WYWnxLHxhzNu3CfnLiqhhaA_YA_iWXR9FYnPDCf_4q3FgSXcgttXzomFKAx5DwnE_dXvsCvpWxslZMU1UIiLA.MHOrrza2GQ9_5PIv.zU4tfhxT6apWBC3stBwQmGlCQBltWVQe4dFIykybWWBFqxo1bf2BZ37twzoEIFXG9jSYEMH4mvBXPWSvn66t-_jnqLnKTJst2plBjhagGCAoLNWXVKeYNp67o-lKOD_JJQFqsRw4oE05VSgRr14MZeaUBFcU3A_kKxMXOu899DKfXBGJvj75H7lDyd8RUXTb-OSWWfUiJc6Y5AUy1zCZCN9yfDsCXt9heTsZANy92Oou9sMFaXkYzyums5OtkBtLFzyuNMEoNioRehTV-FTuL8tDRB1mNhHObwsBfFbR6M1jJK37pHUXGtko-yZ6NGwxyLtwGh4uU2jzE614rQzuzR8aHaHxOkUs1pBTZ8AcRt41snByOe-KU0adthHxedobFiQQBoQ05DgSU7DO6hsK0uVBDF3eG2KjH4L2lZy-WugloLHhdguUoO9F0zUx15-XZO4EVzmhy8xfH2tSXz98eKzz9Dv0DdGnrBL9cK2MM88N1zoq5u4NdlnE12HvuesB7GKdMwZx1-gTw_pzP81TzcctJWl6ETK09Uc.jk0O8qc4Fvip856stDz05Q -``` - -And then make this request: - -```bash -curl -H "Authorization: Bearer $TOKEN" localhost:8080 -``` - -Which will respond with the phrase: - -```bash -Hello, subject! -``` - -where `subject` is the value of the `sub` field in the JWT returned by the Authorization Server. - -Or this: - -```bash -export TOKEN=eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.CRBAEgvQhpB6pPQhpkTAKpsDai1FDcvkDSRig1R3OI-g18JdTe-qDhzWwP-hV3aCwFwHxQ_g8Z8OIZvhyKpQaPwBb72UeLqqhzSIkm0gEsmmjYg1vEGOrDH5_Fqlm0LnAnXTmsbOIWYIj11ZuenI2lEmMCkVwqth0RlzakdcHRXiuDTEln_trhZpE2j80X-9rS2gZy9Raa9VLir3-F3wC0GKPEL6e3x1OygC03ix9uyXS3vpTsU9zlgoYADZyaLeOF1mCG4mQhvXs7IPmPbwNsElJwKh0xSQCHvNOQShprlvd3cHiUFKYw9fXphY1O-AUYcRzHk4DjoBdkGNQMy_Kw.KtC_z674rYBtDgkN.e8QU50Iq1JHkn-1USSxpjEkbrukb4cobvlQRK40iXGAKVIuOod4bSq5fDpIAPHugqIf-_zGsvr-2OCOdzhtBikL46wU7UdZppxPWtk-X6kl33zH_XObRMaGfe-hLxt3RPxRVn7I1Hp6tGW1Rkxyf_ESq4XlcbbrkhDoIz_G_LKXJhvQ-xahW2e0AUc7RZSucns4XUeq9xX_dd7Ht-o1TmQI9WFoFc1l7oh9GtQ6GZMsghnZ1VrbIS2L7jSYiSsD2JqSv1LLtOGj_FBA0ufhqM3LloGiwflEwAryMD10oNb73WonKEycEj1rBsTIKW7SHkI-VkrQA4-8N-aLWgHwDnzyPZmyNyKpqUMvhjIE_0w6oqU4HpN7J5nfBEIAtpPZ_pDkwAdxCQ7JV3zfiUnF7ZQ3q1PnSId315si02ZN9-wRSrMHcHnboQN1Hs4xCAfGyClVyLpCzfa_fAehjt6v1DjgjbzwSjr_LdNmWTvXYBhNO8Jq9Vb7axksrdwksD3pYNMY8cRZxP-LO0V5Sv1_kT_Hf2yLo2iTwB8n8szzGrJ4QQLb5Znu7Sv-M2x52cnIDMiorP3LNpFk.G85FuMSm-8bGumFAStiFQA - -curl -H "Authorization: Bearer $TOKEN" localhost:8080/message -``` - -Will respond with: - -```bash -secret message -``` - -== 2. Testing against other Authorization Servers - -_In order to use this sample, your Authorization Server must encrypt using the public key available in the sample. -Also it must support JWTs that either use the "scope" or "scp" attribute._ - -To change the sample to point at your Authorization Server, simply find this property in the `application.yml`: - -```yaml -spring: - security: - oauth2: - resourceserver: - jwt: - jwk-set-uri: ${mockwebserver.url}/.well-known/jwks.json -``` - -And change the property to your Authorization Server's JWK set endpoint: - -```yaml -spring: - security: - oauth2: - resourceserver: - jwt: - jwk-set-uri: https://localhost:9031/pf/JWKS -``` - -If your Authorization Server does not support RSA_OAEP_256 or AESGCM, then you can change these values in `OAuth2ResourceServerSecurityConfiguration`: - -```java - -``` - -And then you can run the app the same as before: - -```bash -./gradlew bootRun -``` - -Make sure to obtain valid tokens from your Authorization Server in order to play with the sample Resource Server. -To use the `/` endpoint, any valid token from your Authorization Server will do. -To use the `/message` endpoint, the token should have the `message:read` scope. diff --git a/samples/boot/oauth2resourceserver-jwe/spring-security-samples-boot-oauth2resourceserver-jwe.gradle b/samples/boot/oauth2resourceserver-jwe/spring-security-samples-boot-oauth2resourceserver-jwe.gradle deleted file mode 100644 index 2135bb0af6..0000000000 --- a/samples/boot/oauth2resourceserver-jwe/spring-security-samples-boot-oauth2resourceserver-jwe.gradle +++ /dev/null @@ -1,13 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-oauth2-jose') - compile project(':spring-security-oauth2-resource-server') - - compile 'org.springframework.boot:spring-boot-starter-web' - compile 'com.squareup.okhttp3:mockwebserver' - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/oauth2resourceserver-jwe/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java b/samples/boot/oauth2resourceserver-jwe/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java deleted file mode 100644 index cd25346ce8..0000000000 --- a/samples/boot/oauth2resourceserver-jwe/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; - -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.HttpHeaders; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.RequestPostProcessor; - -import static org.hamcrest.Matchers.containsString; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -/** - * Integration tests for {@link OAuth2ResourceServerApplication} - * - * @author Josh Cummings - */ -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -@ActiveProfiles("test") -public class OAuth2ResourceServerApplicationITests { - - String noScopesToken = "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.IyeWtsTonaiWJdoT13B0M7gpqVxAirVGlfqFI4TOmTRcVHICs_ESezS7fa0ODS9XYdwklTtG7hH39yeeMzr2Zo1Ghh-m36fdoqQrV1Do04rUvuTjqbgyNffeZEGB6rquJ-cyAVjp_Oljy10-Bbnw7CeVGwNBSVo9UCB5j49OlNWhLxFpYARFmOlYpXj-s4Q4JiqV6EvjDAYeohAR4QQmND3qoxR-s2I6SLcIho0sSSpUlhrRiqu2uvWefHDcZJdW2WYWnxLHxhzNu3CfnLiqhhaA_YA_iWXR9FYnPDCf_4q3FgSXcgttXzomFKAx5DwnE_dXvsCvpWxslZMU1UIiLA.MHOrrza2GQ9_5PIv.zU4tfhxT6apWBC3stBwQmGlCQBltWVQe4dFIykybWWBFqxo1bf2BZ37twzoEIFXG9jSYEMH4mvBXPWSvn66t-_jnqLnKTJst2plBjhagGCAoLNWXVKeYNp67o-lKOD_JJQFqsRw4oE05VSgRr14MZeaUBFcU3A_kKxMXOu899DKfXBGJvj75H7lDyd8RUXTb-OSWWfUiJc6Y5AUy1zCZCN9yfDsCXt9heTsZANy92Oou9sMFaXkYzyums5OtkBtLFzyuNMEoNioRehTV-FTuL8tDRB1mNhHObwsBfFbR6M1jJK37pHUXGtko-yZ6NGwxyLtwGh4uU2jzE614rQzuzR8aHaHxOkUs1pBTZ8AcRt41snByOe-KU0adthHxedobFiQQBoQ05DgSU7DO6hsK0uVBDF3eG2KjH4L2lZy-WugloLHhdguUoO9F0zUx15-XZO4EVzmhy8xfH2tSXz98eKzz9Dv0DdGnrBL9cK2MM88N1zoq5u4NdlnE12HvuesB7GKdMwZx1-gTw_pzP81TzcctJWl6ETK09Uc.jk0O8qc4Fvip856stDz05Q"; - String messageReadToken = "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAtMjU2In0.CRBAEgvQhpB6pPQhpkTAKpsDai1FDcvkDSRig1R3OI-g18JdTe-qDhzWwP-hV3aCwFwHxQ_g8Z8OIZvhyKpQaPwBb72UeLqqhzSIkm0gEsmmjYg1vEGOrDH5_Fqlm0LnAnXTmsbOIWYIj11ZuenI2lEmMCkVwqth0RlzakdcHRXiuDTEln_trhZpE2j80X-9rS2gZy9Raa9VLir3-F3wC0GKPEL6e3x1OygC03ix9uyXS3vpTsU9zlgoYADZyaLeOF1mCG4mQhvXs7IPmPbwNsElJwKh0xSQCHvNOQShprlvd3cHiUFKYw9fXphY1O-AUYcRzHk4DjoBdkGNQMy_Kw.KtC_z674rYBtDgkN.e8QU50Iq1JHkn-1USSxpjEkbrukb4cobvlQRK40iXGAKVIuOod4bSq5fDpIAPHugqIf-_zGsvr-2OCOdzhtBikL46wU7UdZppxPWtk-X6kl33zH_XObRMaGfe-hLxt3RPxRVn7I1Hp6tGW1Rkxyf_ESq4XlcbbrkhDoIz_G_LKXJhvQ-xahW2e0AUc7RZSucns4XUeq9xX_dd7Ht-o1TmQI9WFoFc1l7oh9GtQ6GZMsghnZ1VrbIS2L7jSYiSsD2JqSv1LLtOGj_FBA0ufhqM3LloGiwflEwAryMD10oNb73WonKEycEj1rBsTIKW7SHkI-VkrQA4-8N-aLWgHwDnzyPZmyNyKpqUMvhjIE_0w6oqU4HpN7J5nfBEIAtpPZ_pDkwAdxCQ7JV3zfiUnF7ZQ3q1PnSId315si02ZN9-wRSrMHcHnboQN1Hs4xCAfGyClVyLpCzfa_fAehjt6v1DjgjbzwSjr_LdNmWTvXYBhNO8Jq9Vb7axksrdwksD3pYNMY8cRZxP-LO0V5Sv1_kT_Hf2yLo2iTwB8n8szzGrJ4QQLb5Znu7Sv-M2x52cnIDMiorP3LNpFk.G85FuMSm-8bGumFAStiFQA"; - - @Autowired - MockMvc mvc; - - @Test - public void performWhenValidBearerTokenThenAllows() - throws Exception { - - this.mvc.perform(get("/").with(bearerToken(this.noScopesToken))) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("Hello, subject!"))); - } - - @Test - public void performWhenValidBearerTokenThenScopedRequestsAlsoWork() - throws Exception { - - this.mvc.perform(get("/message").with(bearerToken(this.messageReadToken))) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("secret message"))); - } - - @Test - public void performWhenInsufficientlyScopedBearerTokenThenDeniesScopedMethodAccess() - throws Exception { - - this.mvc.perform(get("/message").with(bearerToken(this.noScopesToken))) - .andExpect(status().isForbidden()) - .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, - containsString("Bearer error=\"insufficient_scope\""))); - } - - private static class BearerTokenRequestPostProcessor implements RequestPostProcessor { - private String token; - - BearerTokenRequestPostProcessor(String token) { - this.token = token; - } - - @Override - public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { - request.addHeader("Authorization", "Bearer " + this.token); - return request; - } - } - - private static BearerTokenRequestPostProcessor bearerToken(String token) { - return new BearerTokenRequestPostProcessor(token); - } -} diff --git a/samples/boot/oauth2resourceserver-jwe/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java b/samples/boot/oauth2resourceserver-jwe/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java deleted file mode 100644 index 62f91d1a1f..0000000000 --- a/samples/boot/oauth2resourceserver-jwe/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.env; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.boot.SpringApplication; -import org.springframework.core.env.ConfigurableEnvironment; - -/** - * @author Rob Winch - */ -public class MockWebServerEnvironmentPostProcessor - implements EnvironmentPostProcessor, DisposableBean { - - private final MockWebServerPropertySource propertySource = new MockWebServerPropertySource(); - - @Override - public void postProcessEnvironment(ConfigurableEnvironment environment, - SpringApplication application) { - environment.getPropertySources().addFirst(this.propertySource); - } - - @Override - public void destroy() throws Exception { - this.propertySource.destroy(); - } -} diff --git a/samples/boot/oauth2resourceserver-jwe/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java b/samples/boot/oauth2resourceserver-jwe/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java deleted file mode 100644 index 5e9df1d836..0000000000 --- a/samples/boot/oauth2resourceserver-jwe/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.env; - -import java.io.IOException; - -import okhttp3.mockwebserver.Dispatcher; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.core.env.PropertySource; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; - -/** - * @author Rob Winch - */ -public class MockWebServerPropertySource extends PropertySource implements - DisposableBean { - - private static final MockResponse JWKS_RESPONSE = response( - "{\"keys\":[{\"kty\":\"RSA\",\"e\":\"AQAB\",\"use\":\"sig\",\"kid\":\"one\",\"n\":\"i7H90yfquGVhXxekdzXkMaxlIg67Q_ofd7iuFHtgeUx-Iye2QjukuULhl774oITYnZIZsh2UHxRYG8nFypcYZfHJMQes_OYFTkTvRroKll5p3wxSkhpARbkEPFMyMJ5WIm3MeNO2ermMhDWVVeI2xQH-tW6w-C6b5d_F6lrIwCnpZwSv6PQ3kef-rcObp_PZANIo232bvpwyC6uW1W2kpjAvYJhQ8NrkG2oO0ynqEJW2UyoCWRdsT2BLZcFMAcxG3Iw9b9__IbvNoUBwr596JYfzrX0atiKyk4Yg8dJ1wBjHFN2fkHTlzn6HDwTJkj4VNDQvKu4P2zhKn1gmWuxhuQ\"}]}", - 200 - ); - - private static final MockResponse NOT_FOUND_RESPONSE = response( - "{ \"message\" : \"This mock authorization server responds to just one request: GET /.well-known/jwks.json.\" }", - 404 - ); - - /** - * Name of the random {@link PropertySource}. - */ - public static final String MOCK_WEB_SERVER_PROPERTY_SOURCE_NAME = "mockwebserver"; - - private static final String NAME = "mockwebserver.url"; - - private static final Log logger = LogFactory.getLog(MockWebServerPropertySource.class); - - private boolean started; - - public MockWebServerPropertySource() { - super(MOCK_WEB_SERVER_PROPERTY_SOURCE_NAME, new MockWebServer()); - } - - @Override - public Object getProperty(String name) { - if (!name.equals(NAME)) { - return null; - } - if (logger.isTraceEnabled()) { - logger.trace("Looking up the url for '" + name + "'"); - } - String url = getUrl(); - return url; - } - - @Override - public void destroy() throws Exception { - getSource().shutdown(); - } - - /** - * Get's the URL (i.e. "http://localhost:123456") - * @return - */ - private String getUrl() { - MockWebServer mockWebServer = getSource(); - if (!this.started) { - intializeMockWebServer(mockWebServer); - } - String url = mockWebServer.url("").url().toExternalForm(); - return url.substring(0, url.length() - 1); - } - - private void intializeMockWebServer(MockWebServer mockWebServer) { - Dispatcher dispatcher = new Dispatcher() { - @Override - public MockResponse dispatch(RecordedRequest request) { - if ("/.well-known/jwks.json".equals(request.getPath())) { - return JWKS_RESPONSE; - } - - return NOT_FOUND_RESPONSE; - } - }; - - mockWebServer.setDispatcher(dispatcher); - try { - mockWebServer.start(); - this.started = true; - } catch (IOException e) { - throw new RuntimeException("Could not start " + mockWebServer, e); - } - } - - private static MockResponse response(String body, int status) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setResponseCode(status) - .setBody(body); - } - -} diff --git a/samples/boot/oauth2resourceserver-jwe/src/main/java/org/springframework/boot/env/package-info.java b/samples/boot/oauth2resourceserver-jwe/src/main/java/org/springframework/boot/env/package-info.java deleted file mode 100644 index 0226037822..0000000000 --- a/samples/boot/oauth2resourceserver-jwe/src/main/java/org/springframework/boot/env/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * This provides integration of a {@link okhttp3.mockwebserver.MockWebServer} and the - * {@link org.springframework.core.env.Environment} - * @author Rob Winch - */ -package org.springframework.boot.env; diff --git a/samples/boot/oauth2resourceserver-jwe/src/main/java/sample/OAuth2ResourceServerApplication.java b/samples/boot/oauth2resourceserver-jwe/src/main/java/sample/OAuth2ResourceServerApplication.java deleted file mode 100644 index a0841c00f3..0000000000 --- a/samples/boot/oauth2resourceserver-jwe/src/main/java/sample/OAuth2ResourceServerApplication.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Josh Cummings - */ -@SpringBootApplication -public class OAuth2ResourceServerApplication { - - public static void main(String[] args) { - SpringApplication.run(OAuth2ResourceServerApplication.class, args); - } -} diff --git a/samples/boot/oauth2resourceserver-jwe/src/main/java/sample/OAuth2ResourceServerController.java b/samples/boot/oauth2resourceserver-jwe/src/main/java/sample/OAuth2ResourceServerController.java deleted file mode 100644 index f0bcdbe64f..0000000000 --- a/samples/boot/oauth2resourceserver-jwe/src/main/java/sample/OAuth2ResourceServerController.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.oauth2.jwt.Jwt; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author Josh Cummings - */ -@RestController -public class OAuth2ResourceServerController { - - @GetMapping("/") - public String index(@AuthenticationPrincipal Jwt jwt) { - return String.format("Hello, %s!", jwt.getSubject()); - } - - @GetMapping("/message") - public String message() { - return "secret message"; - } -} diff --git a/samples/boot/oauth2resourceserver-jwe/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java b/samples/boot/oauth2resourceserver-jwe/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java deleted file mode 100644 index dfe4135d4b..0000000000 --- a/samples/boot/oauth2resourceserver-jwe/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import java.net.URL; -import java.security.interfaces.RSAPrivateCrtKey; -import java.security.interfaces.RSAPrivateKey; - -import com.nimbusds.jose.EncryptionMethod; -import com.nimbusds.jose.JWEAlgorithm; -import com.nimbusds.jose.JWSAlgorithm; -import com.nimbusds.jose.jwk.JWKSet; -import com.nimbusds.jose.jwk.KeyUse; -import com.nimbusds.jose.jwk.RSAKey; -import com.nimbusds.jose.jwk.source.ImmutableJWKSet; -import com.nimbusds.jose.jwk.source.JWKSource; -import com.nimbusds.jose.jwk.source.RemoteJWKSet; -import com.nimbusds.jose.proc.JWEDecryptionKeySelector; -import com.nimbusds.jose.proc.JWEKeySelector; -import com.nimbusds.jose.proc.JWSKeySelector; -import com.nimbusds.jose.proc.JWSVerificationKeySelector; -import com.nimbusds.jose.proc.SecurityContext; -import com.nimbusds.jose.util.Base64URL; -import com.nimbusds.jwt.proc.ConfigurableJWTProcessor; -import com.nimbusds.jwt.proc.DefaultJWTProcessor; -import com.nimbusds.jwt.proc.JWTProcessor; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -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.WebSecurityConfigurerAdapter; -import org.springframework.security.oauth2.jwt.JwtDecoder; -import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; - -import static org.springframework.security.config.Customizer.withDefaults; - -/** - * @author Josh Cummings - */ -@EnableWebSecurity -public class OAuth2ResourceServerSecurityConfiguration extends WebSecurityConfigurerAdapter { - - private final JWSAlgorithm jwsAlgorithm = JWSAlgorithm.RS256; - private final JWEAlgorithm jweAlgorithm = JWEAlgorithm.RSA_OAEP_256; - private final EncryptionMethod encryptionMethod = EncryptionMethod.A256GCM; - - @Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}") - URL jwkSetUri; - - @Value("${sample.jwe-key-value}") - RSAPrivateKey key; - - @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .authorizeRequests((authorizeRequests) -> - authorizeRequests - .antMatchers("/message/**").hasAuthority("SCOPE_message:read") - .anyRequest().authenticated() - ) - .oauth2ResourceServer((oauth2ResourceServer) -> - oauth2ResourceServer - .jwt(withDefaults()) - ); - // @formatter:on - } - - @Bean - JwtDecoder jwtDecoder() { - return new NimbusJwtDecoder(jwtProcessor()); - } - - private JWTProcessor jwtProcessor() { - JWKSource jwsJwkSource = new RemoteJWKSet<>(this.jwkSetUri); - JWSKeySelector jwsKeySelector = - new JWSVerificationKeySelector<>(this.jwsAlgorithm, jwsJwkSource); - - JWKSource jweJwkSource = new ImmutableJWKSet<>(new JWKSet(rsaKey())); - JWEKeySelector jweKeySelector = - new JWEDecryptionKeySelector<>(this.jweAlgorithm, this.encryptionMethod, jweJwkSource); - - ConfigurableJWTProcessor jwtProcessor = new DefaultJWTProcessor<>(); - jwtProcessor.setJWSKeySelector(jwsKeySelector); - jwtProcessor.setJWEKeySelector(jweKeySelector); - - return jwtProcessor; - } - - private RSAKey rsaKey() { - RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey) this.key; - Base64URL n = Base64URL.encode(crtKey.getModulus()); - Base64URL e = Base64URL.encode(crtKey.getPublicExponent()); - return new RSAKey.Builder(n, e) - .privateKey(this.key) - .keyUse(KeyUse.ENCRYPTION) - .build(); - } -} diff --git a/samples/boot/oauth2resourceserver-jwe/src/main/resources/META-INF/spring.factories b/samples/boot/oauth2resourceserver-jwe/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 37b447c970..0000000000 --- a/samples/boot/oauth2resourceserver-jwe/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1 +0,0 @@ -org.springframework.boot.env.EnvironmentPostProcessor=org.springframework.boot.env.MockWebServerEnvironmentPostProcessor diff --git a/samples/boot/oauth2resourceserver-jwe/src/main/resources/application.yml b/samples/boot/oauth2resourceserver-jwe/src/main/resources/application.yml deleted file mode 100644 index 8573fda8f6..0000000000 --- a/samples/boot/oauth2resourceserver-jwe/src/main/resources/application.yml +++ /dev/null @@ -1,9 +0,0 @@ -spring: - security: - oauth2: - resourceserver: - jwt: - jwk-set-uri: ${mockwebserver.url}/.well-known/jwks.json - -sample: - jwe-key-value: classpath:simple.priv diff --git a/samples/boot/oauth2resourceserver-jwe/src/main/resources/simple.priv b/samples/boot/oauth2resourceserver-jwe/src/main/resources/simple.priv deleted file mode 100644 index 53510079ac..0000000000 --- a/samples/boot/oauth2resourceserver-jwe/src/main/resources/simple.priv +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDcWWomvlNGyQhA -iB0TcN3sP2VuhZ1xNRPxr58lHswC9Cbtdc2hiSbe/sxAvU1i0O8vaXwICdzRZ1JM -g1TohG9zkqqjZDhyw1f1Ic6YR/OhE6NCpqERy97WMFeW6gJd1i5inHj/W19GAbqK -LhSHGHqIjyo0wlBf58t+qFt9h/EFBVE/LAGQBsg/jHUQCxsLoVI2aSELGIw2oSDF -oiljwLaQl0n9khX5ZbiegN3OkqodzCYHwWyu6aVVj8M1W9RIMiKmKr09s/gf31Nc -3WjvjqhFo1rTuurWGgKAxJLL7zlJqAKjGWbIT4P6h/1Kwxjw6X23St3OmhsG6HIn -+jl1++MrAgMBAAECggEBAMf820wop3pyUOwI3aLcaH7YFx5VZMzvqJdNlvpg1jbE -E2Sn66b1zPLNfOIxLcBG8x8r9Ody1Bi2Vsqc0/5o3KKfdgHvnxAB3Z3dPh2WCDek -lCOVClEVoLzziTuuTdGO5/CWJXdWHcVzIjPxmK34eJXioiLaTYqN3XKqKMdpD0ZG -mtNTGvGf+9fQ4i94t0WqIxpMpGt7NM4RHy3+Onggev0zLiDANC23mWrTsUgect/7 -62TYg8g1bKwLAb9wCBT+BiOuCc2wrArRLOJgUkj/F4/gtrR9ima34SvWUyoUaKA0 -bi4YBX9l8oJwFGHbU9uFGEMnH0T/V0KtIB7qetReywkCgYEA9cFyfBIQrYISV/OA -+Z0bo3vh2aL0QgKrSXZ924cLt7itQAHNZ2ya+e3JRlTczi5mnWfjPWZ6eJB/8MlH -Gpn12o/POEkU+XjZZSPe1RWGt5g0S3lWqyx9toCS9ACXcN9tGbaqcFSVI73zVTRA -8J9grR0fbGn7jaTlTX2tnlOTQ60CgYEA5YjYpEq4L8UUMFkuj+BsS3u0oEBnzuHd -I9LEHmN+CMPosvabQu5wkJXLuqo2TxRnAznsA8R3pCLkdPGoWMCiWRAsCn979TdY -QbqO2qvBAD2Q19GtY7lIu6C35/enQWzJUMQE3WW0OvjLzZ0l/9mA2FBRR+3F9A1d -rBdnmv0c3TcCgYEAi2i+ggVZcqPbtgrLOk5WVGo9F1GqUBvlgNn30WWNTx4zIaEk -HSxtyaOLTxtq2odV7Kr3LGiKxwPpn/T+Ief+oIp92YcTn+VfJVGw4Z3BezqbR8lA -Uf/+HF5ZfpMrVXtZD4Igs3I33Duv4sCuqhEvLWTc44pHifVloozNxYfRfU0CgYBN -HXa7a6cJ1Yp829l62QlJKtx6Ymj95oAnQu5Ez2ROiZMqXRO4nucOjGUP55Orac1a -FiGm+mC/skFS0MWgW8evaHGDbWU180wheQ35hW6oKAb7myRHtr4q20ouEtQMdQIF -snV39G1iyqeeAsf7dxWElydXpRi2b68i3BIgzhzebQKBgQCdUQuTsqV9y/JFpu6H -c5TVvhG/ubfBspI5DhQqIGijnVBzFT//UfIYMSKJo75qqBEyP2EJSmCsunWsAFsM -TszuiGTkrKcZy9G0wJqPztZZl2F2+bJgnA6nBEV7g5PA4Af+QSmaIhRwqGDAuROR -47jndeyIaMTNETEmOnms+as17g== ------END PRIVATE KEY----- \ No newline at end of file diff --git a/samples/boot/oauth2resourceserver-jwe/src/main/resources/simple.pub b/samples/boot/oauth2resourceserver-jwe/src/main/resources/simple.pub deleted file mode 100644 index 0b2ee7b336..0000000000 --- a/samples/boot/oauth2resourceserver-jwe/src/main/resources/simple.pub +++ /dev/null @@ -1,9 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3FlqJr5TRskIQIgdE3Dd -7D9lboWdcTUT8a+fJR7MAvQm7XXNoYkm3v7MQL1NYtDvL2l8CAnc0WdSTINU6IRv -c5Kqo2Q4csNX9SHOmEfzoROjQqahEcve1jBXluoCXdYuYpx4/1tfRgG6ii4Uhxh6 -iI8qNMJQX+fLfqhbfYfxBQVRPywBkAbIP4x1EAsbC6FSNmkhCxiMNqEgxaIpY8C2 -kJdJ/ZIV+WW4noDdzpKqHcwmB8FsrumlVY/DNVvUSDIipiq9PbP4H99TXN1o746o -RaNa07rq1hoCgMSSy+85SagCoxlmyE+D+of9SsMY8Ol9t0rdzpobBuhyJ/o5dfvj -KwIDAQAB ------END PUBLIC KEY----- \ No newline at end of file diff --git a/samples/boot/oauth2resourceserver-multitenancy/README.adoc b/samples/boot/oauth2resourceserver-multitenancy/README.adoc deleted file mode 100644 index 97674479bd..0000000000 --- a/samples/boot/oauth2resourceserver-multitenancy/README.adoc +++ /dev/null @@ -1,155 +0,0 @@ -= OAuth 2.0 Resource Server Sample - -This sample demonstrates integrating Resource Server with a mock Authorization Server, though it can be modified to integrate -with your favorite Authorization Server. - -With it, you can run the integration tests or run the application as a stand-alone service to explore how you can -secure your own service with OAuth 2.0 Bearer Tokens using Spring Security. - -== 1. Running the tests - -To run the tests, do: - -```bash -./gradlew integrationTest -``` - -Or import the project into your IDE and run `OAuth2ResourceServerApplicationTests` from there. - -=== What is it doing? - -By default, the tests are pointing at a mock Authorization Server instance. - -The tests are configured with a set of hard-coded tokens originally obtained from the mock Authorization Server, -and each makes a query to the Resource Server with their corresponding token. - -The Resource Server subsequently verifies with the Authorization Server and authorizes the request, returning either the -phrase - -```bash -Hello, subject for tenant one! -``` - -where "subject" is the value of the `sub` field in the JWT sent in the `Authorization` header, - -or the phrase -```bash -Hello, subject for tenant two! -``` -where "subject" is the value of the `sub` field in the Introspection response from the Authorization Server. - - -== 2. Running the app - -To run as a stand-alone application, do: - -```bash -./gradlew bootRun -``` - -Or import the project into your IDE and run `OAuth2ResourceServerApplication` from there. - -=== Authorizing with tenantOne (JWT) - -Once it is up, you can use the following token: - -```bash -export TOKEN=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjo0NjgzODA1MTI4fQ.ULEPdHG-MK5GlrTQMhgqcyug2brTIZaJIrahUeq9zaiwUSdW83fJ7W1IDd2Z3n4a25JY2uhEcoV95lMfccHR6y_2DLrNvfta22SumY9PEDF2pido54LXG6edIGgarnUbJdR4rpRe_5oRGVa8gDx8FnuZsNv6StSZHAzw5OsuevSTJ1UbJm4UfX3wiahFOQ2OI6G-r5TB2rQNdiPHuNyzG5yznUqRIZ7-GCoMqHMaC-1epKxiX8gYXRROuUYTtcMNa86wh7OVDmvwVmFioRcR58UWBRoO1XQexTtOQq_t8KYsrPZhb9gkyW8x2bAQF-d0J0EJY8JslaH6n4RBaZISww -``` - -And then make this request: - -```bash -curl -H "tenant: one" -H "Authorization: Bearer $TOKEN" localhost:8080 -``` - -Which will respond with the phrase: - -```bash -Hello, subject for tenant one! -``` - -where `subject` is the value of the `sub` field in the JWT sent in the `Authorization` header. - -Or this: - -```bash -export TOKEN=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0Iiwic2NvcGUiOiJtZXNzYWdlOnJlYWQiLCJleHAiOjQ2ODM4MDUxNDF9.h-j6FKRFdnTdmAueTZCdep45e6DPwqM68ZQ8doIJ1exi9YxAlbWzOwId6Bd0L5YmCmp63gGQgsBUBLzwnZQ8kLUgUOBEC3UzSWGRqMskCY9_k9pX0iomX6IfF3N0PaYs0WPC4hO1s8wfZQ-6hKQ4KigFi13G9LMLdH58PRMK0pKEvs3gCbHJuEPw-K5ORlpdnleUTQIwINafU57cmK3KocTeknPAM_L716sCuSYGvDl6xUTXO7oPdrXhS_EhxLP6KxrpI1uD4Ea_5OWTh7S0Wx5LLDfU6wBG1DowN20d374zepOIEkR-Jnmr_QlR44vmRqS5ncrF-1R0EGcPX49U6A - -curl -H "tenant: one" -H "Authorization: Bearer $TOKEN" localhost:8080/message -``` - -Will respond with: - -```bash -secret message for tenant one -``` - -=== Authorizing with tenantTwo (Opaque token) - -Once it is up, you can use the following token: - -```bash -export TOKEN=00ed5855-1869-47a0-b0c9-0f3ce520aee7 -``` - -And then make this request: - -```bash -curl -H "tenant: two" -H "Authorization: Bearer $TOKEN" localhost:8080 -``` - -Which will respond with the phrase: - -```bash -Hello, subject for tenant two! -``` - -where `subject` is the value of the `sub` field in the Introspection response from the Authorization Server. - -Or this: - -```bash -export TOKEN=b43d1500-c405-4dc9-b9c9-6cfd966c34c9 - -curl -H "tenant: two" -H "Authorization: Bearer $TOKEN" localhost:8080/message -``` - -Will respond with: - -```bash -secret message for tenant two -``` - -== 2. Testing against other Authorization Servers - -_In order to use this sample, your Authorization Server must support JWTs that either use the "scope" or "scp" attribute._ - -To change the sample to point at your Authorization Server, simply find these properties in the `application.yml`: - -```yaml -tenantOne.jwk-set-uri: ${mockwebserver.url}/.well-known/jwks.json -tenantTwo.introspection-uri: ${mockwebserver.url}/introspect -tenantTwo.introspection-client-id: client -tenantTwo.introspection-client-secret: secret -``` - -And change the properties to your Authorization Server's JWK set endpoint and -introspection endpoint, including its client id and secret - -```yaml -tenantOne.jwk-set-uri: https://dev-123456.oktapreview.com/oauth2/default/v1/keys -tenantTwo.introspection-uri: https://dev-123456.oktapreview.com/oauth2/default/v1/introspect -tenantTwo.introspection-client-id: client -tenantTwo.introspection-client-secret: secret -``` - -And then you can run the app the same as before: - -```bash -./gradlew bootRun -``` - -Make sure to obtain valid tokens from your Authorization Server in order to play with the sample Resource Server. -To use the `/` endpoint, any valid token from your Authorization Server will do. -To use the `/message` endpoint, the token should have the `message:read` scope. diff --git a/samples/boot/oauth2resourceserver-multitenancy/spring-security-samples-boot-oauth2resourceserver-multitenancy.gradle b/samples/boot/oauth2resourceserver-multitenancy/spring-security-samples-boot-oauth2resourceserver-multitenancy.gradle deleted file mode 100644 index 9074842b18..0000000000 --- a/samples/boot/oauth2resourceserver-multitenancy/spring-security-samples-boot-oauth2resourceserver-multitenancy.gradle +++ /dev/null @@ -1,14 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-oauth2-jose') - compile project(':spring-security-oauth2-resource-server') - - compile 'org.springframework.boot:spring-boot-starter-web' - compile 'com.nimbusds:oauth2-oidc-sdk' - compile 'com.squareup.okhttp3:mockwebserver' - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/oauth2resourceserver-multitenancy/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java b/samples/boot/oauth2resourceserver-multitenancy/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java deleted file mode 100644 index be6d3f559c..0000000000 --- a/samples/boot/oauth2resourceserver-multitenancy/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; - -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.HttpHeaders; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; - -import static org.hamcrest.Matchers.containsString; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -/** - * Integration tests for {@link OAuth2ResourceServerApplication} - * - * @author Josh Cummings - */ -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -public class OAuth2ResourceServerApplicationITests { - - String tenantOneNoScopesToken = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjo0NjgzODA1MTI4fQ.ULEPdHG-MK5GlrTQMhgqcyug2brTIZaJIrahUeq9zaiwUSdW83fJ7W1IDd2Z3n4a25JY2uhEcoV95lMfccHR6y_2DLrNvfta22SumY9PEDF2pido54LXG6edIGgarnUbJdR4rpRe_5oRGVa8gDx8FnuZsNv6StSZHAzw5OsuevSTJ1UbJm4UfX3wiahFOQ2OI6G-r5TB2rQNdiPHuNyzG5yznUqRIZ7-GCoMqHMaC-1epKxiX8gYXRROuUYTtcMNa86wh7OVDmvwVmFioRcR58UWBRoO1XQexTtOQq_t8KYsrPZhb9gkyW8x2bAQF-d0J0EJY8JslaH6n4RBaZISww"; - String tenantOneMessageReadToken = "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0Iiwic2NvcGUiOiJtZXNzYWdlOnJlYWQiLCJleHAiOjQ2ODM4MDUxNDF9.h-j6FKRFdnTdmAueTZCdep45e6DPwqM68ZQ8doIJ1exi9YxAlbWzOwId6Bd0L5YmCmp63gGQgsBUBLzwnZQ8kLUgUOBEC3UzSWGRqMskCY9_k9pX0iomX6IfF3N0PaYs0WPC4hO1s8wfZQ-6hKQ4KigFi13G9LMLdH58PRMK0pKEvs3gCbHJuEPw-K5ORlpdnleUTQIwINafU57cmK3KocTeknPAM_L716sCuSYGvDl6xUTXO7oPdrXhS_EhxLP6KxrpI1uD4Ea_5OWTh7S0Wx5LLDfU6wBG1DowN20d374zepOIEkR-Jnmr_QlR44vmRqS5ncrF-1R0EGcPX49U6A"; - String tenantTwoNoScopesToken = "00ed5855-1869-47a0-b0c9-0f3ce520aee7"; - String tenantTwoMessageReadToken = "b43d1500-c405-4dc9-b9c9-6cfd966c34c9"; - - @Autowired - MockMvc mvc; - - @Test - public void tenantOnePerformWhenValidBearerTokenThenAllows() - throws Exception { - - this.mvc.perform(get("/") - .header("tenant", "one") - .header("Authorization", "Bearer " + this.tenantOneNoScopesToken)) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("Hello, subject for tenant one!"))); - } - - @Test - public void tenantOnePerformWhenValidBearerTokenThenScopedRequestsAlsoWork() - throws Exception { - - this.mvc.perform(get("/message") - .header("tenant", "one") - .header("Authorization", "Bearer " + this.tenantOneMessageReadToken)) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("secret message for tenant one"))); - } - - @Test - public void tenantOnePerformWhenInsufficientlyScopedBearerTokenThenDeniesScopedMethodAccess() - throws Exception { - - this.mvc.perform(get("/message") - .header("tenant", "one") - .header("Authorization", "Bearer " + this.tenantOneNoScopesToken)) - .andExpect(status().isForbidden()) - .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, - containsString("Bearer error=\"insufficient_scope\""))); - } - - @Test - public void tenantTwoPerformWhenValidBearerTokenThenAllows() - throws Exception { - - this.mvc.perform(get("/") - .header("tenant", "two") - .header("Authorization", "Bearer " + this.tenantTwoNoScopesToken)) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("Hello, subject for tenant two!"))); - } - - @Test - public void tenantTwoPerformWhenValidBearerTokenThenScopedRequestsAlsoWork() - throws Exception { - - this.mvc.perform(get("/message") - .header("tenant", "two") - .header("Authorization", "Bearer " + this.tenantTwoMessageReadToken)) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("secret message for tenant two"))); - } - - @Test - public void tenantTwoPerformWhenInsufficientlyScopedBearerTokenThenDeniesScopedMethodAccess() - throws Exception { - - this.mvc.perform(get("/message") - .header("tenant", "two") - .header("Authorization", "Bearer " + this.tenantTwoNoScopesToken)) - .andExpect(status().isForbidden()) - .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, - containsString("Bearer error=\"insufficient_scope\""))); - } - - @Test(expected = IllegalArgumentException.class) - public void invalidTenantPerformWhenValidBearerTokenThenThrowsException() - throws Exception { - - this.mvc.perform(get("/") - .header("tenant", "three") - .header("Authorization", "Bearer " + this.tenantOneNoScopesToken)); - } -} diff --git a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java b/samples/boot/oauth2resourceserver-multitenancy/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java deleted file mode 100644 index f6f664891b..0000000000 --- a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.env; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.boot.SpringApplication; -import org.springframework.core.env.ConfigurableEnvironment; - -/** - * @author Rob Winch - */ -public class MockWebServerEnvironmentPostProcessor - implements EnvironmentPostProcessor, DisposableBean { - - private final MockWebServerPropertySource propertySource = new MockWebServerPropertySource(); - - @Override - public void postProcessEnvironment(ConfigurableEnvironment environment, - SpringApplication application) { - environment.getPropertySources().addFirst(this.propertySource); - } - - @Override - public void destroy() throws Exception { - this.propertySource.destroy(); - } -} diff --git a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java b/samples/boot/oauth2resourceserver-multitenancy/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java deleted file mode 100644 index 9e3f58e628..0000000000 --- a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.env; - -import java.io.IOException; -import java.util.Base64; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import okhttp3.mockwebserver.Dispatcher; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import okio.Buffer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.core.env.PropertySource; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; - -/** - * @author Rob Winch - */ -public class MockWebServerPropertySource extends PropertySource implements - DisposableBean { - - // introspection endpoint - - private static final MockResponse NO_SCOPES_RESPONSE = response( - "{\n" + - " \"active\": true,\n" + - " \"sub\": \"subject\"\n" + - " }", - 200 - ); - - private static final MockResponse MESSASGE_READ_SCOPE_RESPONSE = response( - "{\n" + - " \"active\": true,\n" + - " \"scope\" : \"message:read\"," + - " \"sub\": \"subject\"\n" + - " }", - 200 - ); - - private static final MockResponse INACTIVE_RESPONSE = response( - "{\n" + - " \"active\": false,\n" + - " }", - 200 - ); - - private static final MockResponse BAD_REQUEST_RESPONSE = response( - "{ \"message\" : \"This mock authorization server requires a username and password of " + - "client/secret and a POST body of token=${token}\" }", - 400 - ); - - private static final MockResponse NOT_FOUND_RESPONSE = response( - "{ \"message\" : \"This mock authorization server responds to just two requests: POST /introspect" + - " and GET /.well-known/jwks.json.\" }", - 404 - ); - - // jwks endpoint - - private static final MockResponse JWKS_RESPONSE = response( - "{\"keys\":[{\"p\":\"2p-ViY7DE9ZrdWQb544m0Jp7Cv03YCSljqfim9pD4ALhObX0OrAznOiowTjwBky9JGffMwDBVSfJSD9TSU7aH2sbbfi0bZLMdekKAuimudXwUqPDxrrg0BCyvCYgLmKjbVT3zcdylWSog93CNTxGDPzauu-oc0XPNKCXnaDpNvE\",\"kty\":\"RSA\",\"q\":\"sP_QYavrpBvSJ86uoKVGj2AGl78CSsAtpf1ybSY5TwUlorXSdqapRbY69Y271b0aMLzlleUn9ZTBO1dlKV2_dw_lPADHVia8z3pxL-8sUhIXLsgj4acchMk4c9YX-sFh07xENnyZ-_TXm3llPLuL67HUfBC2eKe800TmCYVWc9U\",\"d\":\"bn1nFxCQT4KLTHqo8mo9HvHD0cRNRNdWcKNnnEQkCF6tKbt-ILRyQGP8O40axLd7CoNVG9c9p_-g4-2kwCtLJNv_STLtwfpCY7VN5o6-ZIpfTjiW6duoPrLWq64Hm_4LOBQTiZfUPcLhsuJRHbWqakj-kV_YbUyC2Ocf_dd8IAQcSrAU2SCcDebhDCWwRUFvaa9V5eq0851S9goaA-AJz-JXyePH6ZFr8JxmWkWxYZ5kdcMD-sm9ZbxE0CaEk32l4fE4hR-L8x2dDtjWA-ahKCZ091z-gV3HWtR2JOjvxoNRjxUo3UxaGiFJHWNIl0EYUJZu1Cb-5wIlEI7wPx5mwQ\",\"e\":\"AQAB\",\"use\":\"sig\",\"kid\":\"one\",\"qi\":\"qS0OK48M2CIAA6_4Wdw4EbCaAfcTLf5Oy9t5BOF_PFUKqoSpZ6JsT5H0a_4zkjt-oI969v78OTlvBKbmEyKO-KeytzHBAA5CsLmVcz0THrMSg6oXZqu66MPnvWoZN9FEN5TklPOvBFm8Bg1QZ3k-YMVaM--DLvhaYR95_mqaz50\",\"dp\":\"Too2NozLGD1XrXyhabZvy1E0EuaVFj0UHQPDLSpkZ_2g3BK6Art6T0xmE8RYtmqrKIEIdlI3IliAvyvAx_1D7zWTTRaj-xlZyqJFrnXWL7zj8UxT8PkB-r2E-ILZ3NAi1gxIWezlBTZ8M6NfObDFmbTc_3tJkN_raISo8z_ziIE\",\"dq\":\"U0yhSkY5yOsa9YcMoigGVBWSJLpNHtbg5NypjHrPv8OhWbkOSq7WvSstBkFk5AtyFvvfZLMLIkWWxxGzV0t6f1MoxBtttLrYYyCxwihiiGFhLbAdSuZ1wnxcqA9bC7UVECvrQmVTpsMs8UupfHKbQBpZ8OWAqrnuYNNtG4_4Bt0\",\"n\":\"lygtuZj0lJjqOqIWocF8Bb583QDdq-aaFg8PesOp2-EDda6GqCpL-_NZVOflNGX7XIgjsWHcPsQHsV9gWuOzSJ0iEuWvtQ6eGBP5M6m7pccLNZfwUse8Cb4Ngx3XiTlyuqM7pv0LPyppZusfEHVEdeelou7Dy9k0OQ_nJTI3b2E1WBoHC58CJ453lo4gcBm1efURN3LIVc1V9NQY_ESBKVdwqYyoJPEanURLVGRd6cQKn6YrCbbIRHjqAyqOE-z3KmgDJnPriljfR5XhSGyM9eqD9Xpy6zu_MAeMJJfSArp857zLPk-Wf5VP9STAcjyfdBIybMKnwBYr2qHMT675hQ\"}]}", - 200 - ); - - /** - * Name of the random {@link PropertySource}. - */ - public static final String MOCK_WEB_SERVER_PROPERTY_SOURCE_NAME = "mockwebserver"; - - private static final String NAME = "mockwebserver.url"; - - private static final Log logger = LogFactory.getLog(MockWebServerPropertySource.class); - - private boolean started; - - public MockWebServerPropertySource() { - super(MOCK_WEB_SERVER_PROPERTY_SOURCE_NAME, new MockWebServer()); - } - - @Override - public Object getProperty(String name) { - if (!name.equals(NAME)) { - return null; - } - if (logger.isTraceEnabled()) { - logger.trace("Looking up the url for '" + name + "'"); - } - String url = getUrl(); - return url; - } - - @Override - public void destroy() throws Exception { - getSource().shutdown(); - } - - /** - * Get's the URL (i.e. "http://localhost:123456") - * @return - */ - private String getUrl() { - MockWebServer mockWebServer = getSource(); - if (!this.started) { - intializeMockWebServer(mockWebServer); - } - String url = mockWebServer.url("").url().toExternalForm(); - return url.substring(0, url.length() - 1); - } - - private void intializeMockWebServer(MockWebServer mockWebServer) { - Dispatcher dispatcher = new Dispatcher() { - @Override - public MockResponse dispatch(RecordedRequest request) { - return doDispatch(request); - } - }; - - mockWebServer.setDispatcher(dispatcher); - try { - mockWebServer.start(); - this.started = true; - } catch (IOException e) { - throw new RuntimeException("Could not start " + mockWebServer, e); - } - } - - private MockResponse doDispatch(RecordedRequest request) { - if ("/.well-known/jwks.json".equals(request.getPath())) { - return JWKS_RESPONSE; - } - - if ("/introspect".equals(request.getPath())) { - return Optional.ofNullable(request.getHeader(HttpHeaders.AUTHORIZATION)) - .filter((authorization) -> isAuthorized(authorization, "client", "secret")) - .map((authorization) -> parseBody(request.getBody())) - .map((parameters) -> parameters.get("token")) - .map((token) -> { - if ("00ed5855-1869-47a0-b0c9-0f3ce520aee7".equals(token)) { - return NO_SCOPES_RESPONSE; - } else if ("b43d1500-c405-4dc9-b9c9-6cfd966c34c9".equals(token)) { - return MESSASGE_READ_SCOPE_RESPONSE; - } else { - return INACTIVE_RESPONSE; - } - }) - .orElse(BAD_REQUEST_RESPONSE); - } - - return NOT_FOUND_RESPONSE; - } - - private boolean isAuthorized(String authorization, String username, String password) { - String[] values = new String(Base64.getDecoder().decode(authorization.substring(6))).split(":"); - return username.equals(values[0]) && password.equals(values[1]); - } - - private Map parseBody(Buffer body) { - return Stream.of(body.readUtf8().split("&")) - .map((parameter) -> parameter.split("=")) - .collect(Collectors.toMap((parts) -> parts[0], (parts) -> parts[1])); - } - - private static MockResponse response(String body, int status) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setResponseCode(status) - .setBody(body); - } - -} diff --git a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/org/springframework/boot/env/package-info.java b/samples/boot/oauth2resourceserver-multitenancy/src/main/java/org/springframework/boot/env/package-info.java deleted file mode 100644 index 4db05821da..0000000000 --- a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/org/springframework/boot/env/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * This provides integration of a {@link okhttp3.mockwebserver.MockWebServer} and the - * {@link org.springframework.core.env.Environment} - * @author Rob Winch - */ -package org.springframework.boot.env; diff --git a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/sample/OAuth2ResourceServerApplication.java b/samples/boot/oauth2resourceserver-multitenancy/src/main/java/sample/OAuth2ResourceServerApplication.java deleted file mode 100644 index d5c70cc70d..0000000000 --- a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/sample/OAuth2ResourceServerApplication.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Josh Cummings - */ -@SpringBootApplication -public class OAuth2ResourceServerApplication { - - public static void main(String[] args) { - SpringApplication.run(OAuth2ResourceServerApplication.class, args); - } -} diff --git a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/sample/OAuth2ResourceServerController.java b/samples/boot/oauth2resourceserver-multitenancy/src/main/java/sample/OAuth2ResourceServerController.java deleted file mode 100644 index 1dce6e718a..0000000000 --- a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/sample/OAuth2ResourceServerController.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author Josh Cummings - */ -@RestController -public class OAuth2ResourceServerController { - - @GetMapping("/") - public String index(@AuthenticationPrincipal OAuth2AuthenticatedPrincipal token, @RequestHeader("tenant") String tenant) { - String subject = token.getAttribute("sub"); - return String.format("Hello, %s for tenant %s!", subject, tenant); - } - - @GetMapping("/message") - public String message(@RequestHeader("tenant") String tenant) { - return String.format("secret message for tenant %s", tenant); - } -} diff --git a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java b/samples/boot/oauth2resourceserver-multitenancy/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java deleted file mode 100644 index 75bf3865b9..0000000000 --- a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import javax.servlet.http.HttpServletRequest; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.AuthenticationManagerResolver; -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.WebSecurityConfigurerAdapter; - -/** - * @author Josh Cummings - */ -@EnableWebSecurity -public class OAuth2ResourceServerSecurityConfiguration extends WebSecurityConfigurerAdapter { - - @Autowired - AuthenticationManagerResolver authenticationManagerResolver; - - @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .authorizeRequests((authz) -> authz - .antMatchers("/message/**").hasAuthority("SCOPE_message:read") - .anyRequest().authenticated() - ) - .oauth2ResourceServer((oauth2) -> oauth2 - .authenticationManagerResolver(this.authenticationManagerResolver) - ); - // @formatter:on - } -} diff --git a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/sample/TenantAuthenticationManagerResolver.java b/samples/boot/oauth2resourceserver-multitenancy/src/main/java/sample/TenantAuthenticationManagerResolver.java deleted file mode 100644 index 939bfc0b8b..0000000000 --- a/samples/boot/oauth2resourceserver-multitenancy/src/main/java/sample/TenantAuthenticationManagerResolver.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import javax.servlet.http.HttpServletRequest; - -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.AuthenticationManagerResolver; -import org.springframework.security.authentication.ProviderManager; -import org.springframework.security.oauth2.jwt.JwtDecoder; -import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationProvider; -import org.springframework.security.oauth2.server.resource.authentication.JwtBearerTokenAuthenticationConverter; -import org.springframework.security.oauth2.server.resource.authentication.OpaqueTokenAuthenticationProvider; -import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector; -import org.springframework.stereotype.Component; - -@Component -public class TenantAuthenticationManagerResolver - implements AuthenticationManagerResolver { - - private AuthenticationManager jwt; - private AuthenticationManager opaqueToken; - - public TenantAuthenticationManagerResolver( - JwtDecoder jwtDecoder, OpaqueTokenIntrospector opaqueTokenIntrospector) { - - JwtAuthenticationProvider jwtAuthenticationProvider = new JwtAuthenticationProvider(jwtDecoder); - jwtAuthenticationProvider.setJwtAuthenticationConverter(new JwtBearerTokenAuthenticationConverter()); - this.jwt = new ProviderManager(jwtAuthenticationProvider); - this.opaqueToken = new ProviderManager(new OpaqueTokenAuthenticationProvider(opaqueTokenIntrospector)); - } - - @Override - public AuthenticationManager resolve(HttpServletRequest request) { - String tenant = request.getHeader("tenant"); - if ("one".equals(tenant)) { - return this.jwt; - } - if ("two".equals(tenant)) { - return this.opaqueToken; - } - throw new IllegalArgumentException("unknown tenant"); - } -} diff --git a/samples/boot/oauth2resourceserver-multitenancy/src/main/resources/META-INF/spring.factories b/samples/boot/oauth2resourceserver-multitenancy/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 37b447c970..0000000000 --- a/samples/boot/oauth2resourceserver-multitenancy/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1 +0,0 @@ -org.springframework.boot.env.EnvironmentPostProcessor=org.springframework.boot.env.MockWebServerEnvironmentPostProcessor diff --git a/samples/boot/oauth2resourceserver-multitenancy/src/main/resources/application.yml b/samples/boot/oauth2resourceserver-multitenancy/src/main/resources/application.yml deleted file mode 100644 index 6447ad0d94..0000000000 --- a/samples/boot/oauth2resourceserver-multitenancy/src/main/resources/application.yml +++ /dev/null @@ -1,10 +0,0 @@ -spring: - security: - oauth2: - resourceserver: - jwt: - jwk-set-uri: ${mockwebserver.url}/.well-known/jwks.json - opaquetoken: - introspection-uri: ${mockwebserver.url}/introspect - client-id: client - client-secret: secret diff --git a/samples/boot/oauth2resourceserver-opaque/README.adoc b/samples/boot/oauth2resourceserver-opaque/README.adoc deleted file mode 100644 index fc6add9a1f..0000000000 --- a/samples/boot/oauth2resourceserver-opaque/README.adoc +++ /dev/null @@ -1,114 +0,0 @@ -= OAuth 2.0 Resource Server Sample - -This sample demonstrates integrating Resource Server with a mock Authorization Server, though it can be modified to integrate -with your favorite Authorization Server. - -With it, you can run the integration tests or run the application as a stand-alone service to explore how you can -secure your own service with OAuth 2.0 Opaque Bearer Tokens using Spring Security. - -== 1. Running the tests - -To run the tests, do: - -```bash -./gradlew integrationTest -``` - -Or import the project into your IDE and run `OAuth2ResourceServerApplicationTests` from there. - -=== What is it doing? - -By default, the tests are pointing at a mock Authorization Server instance. - -The tests are configured with a set of hard-coded tokens originally obtained from the mock Authorization Server, -and each makes a query to the Resource Server with their corresponding token. - -The Resource Server subsquently verifies with the Authorization Server and authorizes the request, returning the phrase - -```bash -Hello, subject! -``` - -where "subject" is the value of the `sub` field in the JWT returned by the Authorization Server. - -== 2. Running the app - -To run as a stand-alone application, do: - -```bash -./gradlew bootRun -``` - -Or import the project into your IDE and run `OAuth2ResourceServerApplication` from there. - -Once it is up, you can use the following token: - -```bash -export TOKEN=00ed5855-1869-47a0-b0c9-0f3ce520aee7 -``` - -And then make this request: - -```bash -curl -H "Authorization: Bearer $TOKEN" localhost:8080 -``` - -Which will respond with the phrase: - -```bash -Hello, subject! -``` - -where `subject` is the value of the `sub` field in the JWT returned by the Authorization Server. - -Or this: - -```bash -export TOKEN=b43d1500-c405-4dc9-b9c9-6cfd966c34c9 - -curl -H "Authorization: Bearer $TOKEN" localhost:8080/message -``` - -Will respond with: - -```bash -secret message -``` - -== 2. Testing against other Authorization Servers - -_In order to use this sample, your Authorization Server must support Opaque Tokens and the Introspection Endpoint. - -To change the sample to point at your Authorization Server, simply find this property in the `application.yml`: - -```yaml -spring: - security: - oauth2: - resourceserver: - opaque: - introspection-uri: ${mockwebserver.url}/introspect - introspection-client-id: client - introspection-client-secret: secret -``` - -And change the property to your Authorization Server's Introspection endpoint, including its client id and secret: - -```yaml -spring: - security: - oauth2: - resourceserver: - opaque: - introspection-uri: ${mockwebserver.url}/introspect -``` - -And then you can run the app the same as before: - -```bash -./gradlew bootRun -``` - -Make sure to obtain valid tokens from your Authorization Server in order to play with the sample Resource Server. -To use the `/` endpoint, any valid token from your Authorization Server will do. -To use the `/message` endpoint, the token should have the `message:read` scope. diff --git a/samples/boot/oauth2resourceserver-opaque/spring-security-samples-boot-oauth2resourceserver-opaque.gradle b/samples/boot/oauth2resourceserver-opaque/spring-security-samples-boot-oauth2resourceserver-opaque.gradle deleted file mode 100644 index 9074842b18..0000000000 --- a/samples/boot/oauth2resourceserver-opaque/spring-security-samples-boot-oauth2resourceserver-opaque.gradle +++ /dev/null @@ -1,14 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-oauth2-jose') - compile project(':spring-security-oauth2-resource-server') - - compile 'org.springframework.boot:spring-boot-starter-web' - compile 'com.nimbusds:oauth2-oidc-sdk' - compile 'com.squareup.okhttp3:mockwebserver' - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/oauth2resourceserver-opaque/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java b/samples/boot/oauth2resourceserver-opaque/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java deleted file mode 100644 index 10bd3fc7ec..0000000000 --- a/samples/boot/oauth2resourceserver-opaque/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; - -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.HttpHeaders; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.RequestPostProcessor; - -import static org.hamcrest.Matchers.containsString; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -/** - * Integration tests for {@link OAuth2ResourceServerApplication} - * - * @author Josh Cummings - */ -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -@ActiveProfiles("test") -public class OAuth2ResourceServerApplicationITests { - - String noScopesToken = "00ed5855-1869-47a0-b0c9-0f3ce520aee7"; - String messageReadToken = "b43d1500-c405-4dc9-b9c9-6cfd966c34c9"; - - @Autowired - MockMvc mvc; - - @Test - public void performWhenValidBearerTokenThenAllows() - throws Exception { - - this.mvc.perform(get("/").with(bearerToken(this.noScopesToken))) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("Hello, subject!"))); - } - - @Test - public void performWhenValidBearerTokenThenScopedRequestsAlsoWork() - throws Exception { - - this.mvc.perform(get("/message").with(bearerToken(this.messageReadToken))) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("secret message"))); - } - - @Test - public void performWhenInsufficientlyScopedBearerTokenThenDeniesScopedMethodAccess() - throws Exception { - - this.mvc.perform(get("/message").with(bearerToken(this.noScopesToken))) - .andExpect(status().isForbidden()) - .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, - containsString("Bearer error=\"insufficient_scope\""))); - } - - private static class BearerTokenRequestPostProcessor implements RequestPostProcessor { - private String token; - - BearerTokenRequestPostProcessor(String token) { - this.token = token; - } - - @Override - public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { - request.addHeader("Authorization", "Bearer " + this.token); - return request; - } - } - - private static BearerTokenRequestPostProcessor bearerToken(String token) { - return new BearerTokenRequestPostProcessor(token); - } -} diff --git a/samples/boot/oauth2resourceserver-opaque/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java b/samples/boot/oauth2resourceserver-opaque/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java deleted file mode 100644 index f6f664891b..0000000000 --- a/samples/boot/oauth2resourceserver-opaque/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.env; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.boot.SpringApplication; -import org.springframework.core.env.ConfigurableEnvironment; - -/** - * @author Rob Winch - */ -public class MockWebServerEnvironmentPostProcessor - implements EnvironmentPostProcessor, DisposableBean { - - private final MockWebServerPropertySource propertySource = new MockWebServerPropertySource(); - - @Override - public void postProcessEnvironment(ConfigurableEnvironment environment, - SpringApplication application) { - environment.getPropertySources().addFirst(this.propertySource); - } - - @Override - public void destroy() throws Exception { - this.propertySource.destroy(); - } -} diff --git a/samples/boot/oauth2resourceserver-opaque/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java b/samples/boot/oauth2resourceserver-opaque/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java deleted file mode 100644 index 0bc6b57558..0000000000 --- a/samples/boot/oauth2resourceserver-opaque/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.env; - -import java.io.IOException; -import java.util.Base64; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import okhttp3.mockwebserver.Dispatcher; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import okio.Buffer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.core.env.PropertySource; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; - -/** - * @author Rob Winch - */ -public class MockWebServerPropertySource extends PropertySource implements - DisposableBean { - - private static final MockResponse NO_SCOPES_RESPONSE = response( - "{\n" + - " \"active\": true,\n" + - " \"sub\": \"subject\"\n" + - " }", - 200 - ); - - private static final MockResponse MESSASGE_READ_SCOPE_RESPONSE = response( - "{\n" + - " \"active\": true,\n" + - " \"scope\" : \"message:read\"," + - " \"sub\": \"subject\"\n" + - " }", - 200 - ); - - private static final MockResponse INACTIVE_RESPONSE = response( - "{\n" + - " \"active\": false,\n" + - " }", - 200 - ); - - private static final MockResponse BAD_REQUEST_RESPONSE = response( - "{ \"message\" : \"This mock authorization server requires a username and password of " + - "client/secret and a POST body of token=${token}\" }", - 400 - ); - - private static final MockResponse NOT_FOUND_RESPONSE = response( - "{ \"message\" : \"This mock authorization server responds to just one request: POST /introspect.\" }", - 404 - ); - - /** - * Name of the random {@link PropertySource}. - */ - public static final String MOCK_WEB_SERVER_PROPERTY_SOURCE_NAME = "mockwebserver"; - - private static final String NAME = "mockwebserver.url"; - - private static final Log logger = LogFactory.getLog(MockWebServerPropertySource.class); - - private boolean started; - - public MockWebServerPropertySource() { - super(MOCK_WEB_SERVER_PROPERTY_SOURCE_NAME, new MockWebServer()); - } - - @Override - public Object getProperty(String name) { - if (!name.equals(NAME)) { - return null; - } - if (logger.isTraceEnabled()) { - logger.trace("Looking up the url for '" + name + "'"); - } - String url = getUrl(); - return url; - } - - @Override - public void destroy() throws Exception { - getSource().shutdown(); - } - - /** - * Get's the URL (e.g. "http://localhost:123456") - * @return - */ - private String getUrl() { - MockWebServer mockWebServer = getSource(); - if (!this.started) { - initializeMockWebServer(mockWebServer); - } - String url = mockWebServer.url("").url().toExternalForm(); - return url.substring(0, url.length() - 1); - } - - private void initializeMockWebServer(MockWebServer mockWebServer) { - Dispatcher dispatcher = new Dispatcher() { - @Override - public MockResponse dispatch(RecordedRequest request) { - return doDispatch(request); - } - }; - - mockWebServer.setDispatcher(dispatcher); - try { - mockWebServer.start(); - this.started = true; - } catch (IOException e) { - throw new RuntimeException("Could not start " + mockWebServer, e); - } - } - - private MockResponse doDispatch(RecordedRequest request) { - if ("/introspect".equals(request.getPath())) { - return Optional.ofNullable(request.getHeader(HttpHeaders.AUTHORIZATION)) - .filter((authorization) -> isAuthorized(authorization, "client", "secret")) - .map((authorization) -> parseBody(request.getBody())) - .map((parameters) -> parameters.get("token")) - .map((token) -> { - if ("00ed5855-1869-47a0-b0c9-0f3ce520aee7".equals(token)) { - return NO_SCOPES_RESPONSE; - } else if ("b43d1500-c405-4dc9-b9c9-6cfd966c34c9".equals(token)) { - return MESSASGE_READ_SCOPE_RESPONSE; - } else { - return INACTIVE_RESPONSE; - } - }) - .orElse(BAD_REQUEST_RESPONSE); - } - - return NOT_FOUND_RESPONSE; - } - - private boolean isAuthorized(String authorization, String username, String password) { - String[] values = new String(Base64.getDecoder().decode(authorization.substring(6))).split(":"); - return username.equals(values[0]) && password.equals(values[1]); - } - - private Map parseBody(Buffer body) { - return Stream.of(body.readUtf8().split("&")) - .map((parameter) -> parameter.split("=")) - .collect(Collectors.toMap((parts) -> parts[0], (parts) -> parts[1])); - } - - private static MockResponse response(String body, int status) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setResponseCode(status) - .setBody(body); - } - -} diff --git a/samples/boot/oauth2resourceserver-opaque/src/main/java/org/springframework/boot/env/package-info.java b/samples/boot/oauth2resourceserver-opaque/src/main/java/org/springframework/boot/env/package-info.java deleted file mode 100644 index 22b7245ebb..0000000000 --- a/samples/boot/oauth2resourceserver-opaque/src/main/java/org/springframework/boot/env/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * This provides integration of a {@link okhttp3.mockwebserver.MockWebServer} and the - * {@link org.springframework.core.env.Environment} - * - * @author Rob Winch - */ -package org.springframework.boot.env; diff --git a/samples/boot/oauth2resourceserver-opaque/src/main/java/sample/OAuth2ResourceServerApplication.java b/samples/boot/oauth2resourceserver-opaque/src/main/java/sample/OAuth2ResourceServerApplication.java deleted file mode 100644 index d5c70cc70d..0000000000 --- a/samples/boot/oauth2resourceserver-opaque/src/main/java/sample/OAuth2ResourceServerApplication.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Josh Cummings - */ -@SpringBootApplication -public class OAuth2ResourceServerApplication { - - public static void main(String[] args) { - SpringApplication.run(OAuth2ResourceServerApplication.class, args); - } -} diff --git a/samples/boot/oauth2resourceserver-opaque/src/main/java/sample/OAuth2ResourceServerController.java b/samples/boot/oauth2resourceserver-opaque/src/main/java/sample/OAuth2ResourceServerController.java deleted file mode 100644 index 857d29be66..0000000000 --- a/samples/boot/oauth2resourceserver-opaque/src/main/java/sample/OAuth2ResourceServerController.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author Josh Cummings - */ -@RestController -public class OAuth2ResourceServerController { - - @GetMapping("/") - public String index(@AuthenticationPrincipal(expression="subject") String subject) { - return String.format("Hello, %s!", subject); - } - - @GetMapping("/message") - public String message() { - return "secret message"; - } - - @PostMapping("/message") - public String createMessage(@RequestBody String message) { - return String.format("Message was created. Content: %s", message); - } -} diff --git a/samples/boot/oauth2resourceserver-opaque/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java b/samples/boot/oauth2resourceserver-opaque/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java deleted file mode 100644 index 6fc3444c73..0000000000 --- a/samples/boot/oauth2resourceserver-opaque/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpMethod; -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.WebSecurityConfigurerAdapter; - -/** - * @author Josh Cummings - */ -@EnableWebSecurity -public class OAuth2ResourceServerSecurityConfiguration extends WebSecurityConfigurerAdapter { - - @Value("${spring.security.oauth2.resourceserver.opaque.introspection-uri}") String introspectionUri; - @Value("${spring.security.oauth2.resourceserver.opaque.introspection-client-id}") String clientId; - @Value("${spring.security.oauth2.resourceserver.opaque.introspection-client-secret}") String clientSecret; - - @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .authorizeRequests((authorizeRequests) -> - authorizeRequests - .antMatchers(HttpMethod.GET, "/message/**").hasAuthority("SCOPE_message:read") - .antMatchers(HttpMethod.POST, "/message/**").hasAuthority("SCOPE_message:write") - .anyRequest().authenticated() - ) - .oauth2ResourceServer((oauth2ResourceServer) -> - oauth2ResourceServer - .opaqueToken((opaqueToken) -> - opaqueToken - .introspectionUri(this.introspectionUri) - .introspectionClientCredentials(this.clientId, this.clientSecret) - ) - ); - // @formatter:on - } -} diff --git a/samples/boot/oauth2resourceserver-opaque/src/main/resources/META-INF/spring.factories b/samples/boot/oauth2resourceserver-opaque/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 37b447c970..0000000000 --- a/samples/boot/oauth2resourceserver-opaque/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1 +0,0 @@ -org.springframework.boot.env.EnvironmentPostProcessor=org.springframework.boot.env.MockWebServerEnvironmentPostProcessor diff --git a/samples/boot/oauth2resourceserver-opaque/src/main/resources/application.yml b/samples/boot/oauth2resourceserver-opaque/src/main/resources/application.yml deleted file mode 100644 index a7dcfead94..0000000000 --- a/samples/boot/oauth2resourceserver-opaque/src/main/resources/application.yml +++ /dev/null @@ -1,8 +0,0 @@ -spring: - security: - oauth2: - resourceserver: - opaque: - introspection-uri: ${mockwebserver.url}/introspect - introspection-client-id: client - introspection-client-secret: secret diff --git a/samples/boot/oauth2resourceserver-opaque/src/test/java/sample/OAuth2ResourceServerControllerTests.java b/samples/boot/oauth2resourceserver-opaque/src/test/java/sample/OAuth2ResourceServerControllerTests.java deleted file mode 100644 index ee3318f246..0000000000 --- a/samples/boot/oauth2resourceserver-opaque/src/test/java/sample/OAuth2ResourceServerControllerTests.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; - -import static org.hamcrest.CoreMatchers.is; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.opaqueToken; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -/** - * @author Josh Cummings - * @since 5.3 - */ -@RunWith(SpringRunner.class) -@WebMvcTest(OAuth2ResourceServerController.class) -public class OAuth2ResourceServerControllerTests { - - @Autowired - MockMvc mvc; - - @Test - public void indexGreetsAuthenticatedUser() throws Exception { - this.mvc.perform(get("/").with(opaqueToken().attributes((a) -> a.put("sub", "ch4mpy")))) - .andExpect(content().string(is("Hello, ch4mpy!"))); - } - - @Test - public void messageCanBeReadWithScopeMessageReadAuthority() throws Exception { - this.mvc.perform(get("/message").with(opaqueToken().attributes((a) -> a.put("scope", "message:read")))) - .andExpect(content().string(is("secret message"))); - - this.mvc.perform(get("/message") - .with(jwt().authorities(new SimpleGrantedAuthority(("SCOPE_message:read"))))) - .andExpect(content().string(is("secret message"))); - } - - @Test - public void messageCanNotBeReadWithoutScopeMessageReadAuthority() throws Exception { - this.mvc.perform(get("/message").with(opaqueToken())) - .andExpect(status().isForbidden()); - } - - @Test - public void messageCanNotBeCreatedWithoutAnyScope() throws Exception { - this.mvc.perform(post("/message") - .content("Hello message") - .with(opaqueToken())) - .andExpect(status().isForbidden()); - } - - @Test - public void messageCanNotBeCreatedWithScopeMessageReadAuthority() throws Exception { - this.mvc.perform(post("/message") - .content("Hello message") - .with(opaqueToken().authorities(new SimpleGrantedAuthority("SCOPE_message:read")))) - .andExpect(status().isForbidden()); - } - - @Test - public void messageCanBeCreatedWithScopeMessageWriteAuthority() throws Exception { - this.mvc.perform(post("/message") - .content("Hello message") - .with(opaqueToken().authorities(new SimpleGrantedAuthority("SCOPE_message:write")))) - .andExpect(status().isOk()) - .andExpect(content().string(is("Message was created. Content: Hello message"))); - } -} diff --git a/samples/boot/oauth2resourceserver-static/README.adoc b/samples/boot/oauth2resourceserver-static/README.adoc deleted file mode 100644 index ecc530d724..0000000000 --- a/samples/boot/oauth2resourceserver-static/README.adoc +++ /dev/null @@ -1,82 +0,0 @@ -= OAuth 2.0 Resource Server Sample - -This sample demonstrates integrating Resource Server with a pre-configured key. - -With it, you can run the integration tests or run the application as a stand-alone service to explore how you can -secure your own service with OAuth 2.0 Bearer Tokens using Spring Security. - -== 1. Running the tests - -To run the tests, do: - -```bash -./gradlew integrationTest -``` - -Or import the project into your IDE and run `OAuth2ResourceServerApplicationITests` from there. - -=== What is it doing? - -By default, the application is configured with an RSA public key that is available in the sample. - -The tests are configured with a set of hard-coded tokens that are signed with the corresponding RSA private key. -Each test makes a query to the Resource Server with their corresponding token. - -The Resource Server subsequently verifies the token against the public key and authorizes the request, returning the phrase - -```bash -Hello, subject! -``` - -where "subject" is the value of the `sub` field in the token. - -== 2. Running the app - -To run as a stand-alone application, do: - -```bash -./gradlew bootRun -``` - -Or import the project into your IDE and run `OAuth2ResourceServerApplication` from there. - -Once it is up, you can use the following token: - -```bash -export TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiaWF0IjoxNTE2MjM5MDIyfQ.eB2c9xtg5wcCZxZ-o-sH4Mx1JGkqAZwH4_WS0UcDbj_nen0NPBj6CqOEPhr_LZDagb4mM6HoAPJywWWG8b_Ylnn5r2gWDzib2mb0kxIuAjnvVBrpzusw4ItTVvP_srv2DrwcisKYiKqU5X_3ka7MSVvKtswdLY3RXeCJ_S2W9go -``` - -And then make this request: - -```bash -curl -H "Authorization: Bearer $TOKEN" localhost:8080 -``` - -Which will respond with the phrase: - -```bash -Hello, subject! -``` - -where `subject` is the value of the `sub` field in the token. - -Or this: - -```bash -export TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiaWF0IjoxNTE2MjM5MDIyLCJzY29wZSI6Im1lc3NhZ2U6cmVhZCJ9.bsRCpUEaiWnzX4OqNxTBqwUD4vxxtPp-CHKTw7XcrglrvZ2lvYXaiZZbCp-hcPhuzMEzEAFuH6s4GZZOWVIX-wT47GdTz9cfA-Z4QPjS2RxePKphFXgBI3jHEpQo94Qya2fJdV4LvgBmA1uM_RTnYY1UbmeYuHKnXrZoGyV8QQQ - -curl -H "Authorization: Bearer $TOKEN" localhost:8080/message -``` - -Will respond with: - -```bash -secret message -``` - -== 3. Testing with Other Tokens - -You can create your own tokens. Simply edit the public key in `OAuth2ResourceServerSecurityConfiguration` to match the private key you use. - -To use the `/` endpoint, any valid token will do. -To use the `/message` endpoint, the token should have the `message:read` scope. diff --git a/samples/boot/oauth2resourceserver-static/spring-security-samples-boot-oauth2resourceserver-static.gradle b/samples/boot/oauth2resourceserver-static/spring-security-samples-boot-oauth2resourceserver-static.gradle deleted file mode 100644 index faba0d5f46..0000000000 --- a/samples/boot/oauth2resourceserver-static/spring-security-samples-boot-oauth2resourceserver-static.gradle +++ /dev/null @@ -1,12 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-oauth2-jose') - compile project(':spring-security-oauth2-resource-server') - - compile 'org.springframework.boot:spring-boot-starter-web' - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/oauth2resourceserver-static/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java b/samples/boot/oauth2resourceserver-static/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java deleted file mode 100644 index 851d3bd242..0000000000 --- a/samples/boot/oauth2resourceserver-static/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; - -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.HttpHeaders; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.RequestPostProcessor; - -import static org.hamcrest.Matchers.containsString; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -/** - * Integration tests for {@link OAuth2ResourceServerApplication} - * - * @author Josh Cummings - */ -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -@ActiveProfiles("test") -public class OAuth2ResourceServerApplicationITests { - - String noScopesToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiaWF0IjoxNTE2MjM5MDIyfQ.eB2c9xtg5wcCZxZ-o-sH4Mx1JGkqAZwH4_WS0UcDbj_nen0NPBj6CqOEPhr_LZDagb4mM6HoAPJywWWG8b_Ylnn5r2gWDzib2mb0kxIuAjnvVBrpzusw4ItTVvP_srv2DrwcisKYiKqU5X_3ka7MSVvKtswdLY3RXeCJ_S2W9go"; - String messageReadToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiaWF0IjoxNTE2MjM5MDIyLCJzY29wZSI6Im1lc3NhZ2U6cmVhZCJ9.bsRCpUEaiWnzX4OqNxTBqwUD4vxxtPp-CHKTw7XcrglrvZ2lvYXaiZZbCp-hcPhuzMEzEAFuH6s4GZZOWVIX-wT47GdTz9cfA-Z4QPjS2RxePKphFXgBI3jHEpQo94Qya2fJdV4LvgBmA1uM_RTnYY1UbmeYuHKnXrZoGyV8QQQ"; - - @Autowired - MockMvc mvc; - - @Test - public void performWhenValidBearerTokenThenAllows() - throws Exception { - - this.mvc.perform(get("/").with(bearerToken(this.noScopesToken))) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("Hello, subject!"))); - } - - @Test - public void performWhenValidBearerTokenThenScopedRequestsAlsoWork() - throws Exception { - - this.mvc.perform(get("/message").with(bearerToken(this.messageReadToken))) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("secret message"))); - } - - @Test - public void performWhenInsufficientlyScopedBearerTokenThenDeniesScopedMethodAccess() - throws Exception { - - this.mvc.perform(get("/message").with(bearerToken(this.noScopesToken))) - .andExpect(status().isForbidden()) - .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, - containsString("Bearer error=\"insufficient_scope\""))); - } - - private static class BearerTokenRequestPostProcessor implements RequestPostProcessor { - private String token; - - BearerTokenRequestPostProcessor(String token) { - this.token = token; - } - - @Override - public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { - request.addHeader("Authorization", "Bearer " + this.token); - return request; - } - } - - private static BearerTokenRequestPostProcessor bearerToken(String token) { - return new BearerTokenRequestPostProcessor(token); - } -} diff --git a/samples/boot/oauth2resourceserver-static/src/main/java/sample/OAuth2ResourceServerApplication.java b/samples/boot/oauth2resourceserver-static/src/main/java/sample/OAuth2ResourceServerApplication.java deleted file mode 100644 index a0841c00f3..0000000000 --- a/samples/boot/oauth2resourceserver-static/src/main/java/sample/OAuth2ResourceServerApplication.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Josh Cummings - */ -@SpringBootApplication -public class OAuth2ResourceServerApplication { - - public static void main(String[] args) { - SpringApplication.run(OAuth2ResourceServerApplication.class, args); - } -} diff --git a/samples/boot/oauth2resourceserver-static/src/main/java/sample/OAuth2ResourceServerController.java b/samples/boot/oauth2resourceserver-static/src/main/java/sample/OAuth2ResourceServerController.java deleted file mode 100644 index f0bcdbe64f..0000000000 --- a/samples/boot/oauth2resourceserver-static/src/main/java/sample/OAuth2ResourceServerController.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.oauth2.jwt.Jwt; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author Josh Cummings - */ -@RestController -public class OAuth2ResourceServerController { - - @GetMapping("/") - public String index(@AuthenticationPrincipal Jwt jwt) { - return String.format("Hello, %s!", jwt.getSubject()); - } - - @GetMapping("/message") - public String message() { - return "secret message"; - } -} diff --git a/samples/boot/oauth2resourceserver-static/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java b/samples/boot/oauth2resourceserver-static/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java deleted file mode 100644 index a57bed2d51..0000000000 --- a/samples/boot/oauth2resourceserver-static/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import java.security.interfaces.RSAPublicKey; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -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.WebSecurityConfigurerAdapter; -import org.springframework.security.oauth2.jwt.JwtDecoder; -import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; - -/** - * @author Josh Cummings - */ -@EnableWebSecurity -public class OAuth2ResourceServerSecurityConfiguration extends WebSecurityConfigurerAdapter { - - @Value("${spring.security.oauth2.resourceserver.jwt.key-value}") - RSAPublicKey key; - - @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .authorizeRequests((authorizeRequests) -> - authorizeRequests - .antMatchers("/message/**").hasAuthority("SCOPE_message:read") - .anyRequest().authenticated() - ) - .oauth2ResourceServer((oauth2ResourceServer) -> - oauth2ResourceServer - .jwt((jwt) -> - jwt.decoder(jwtDecoder()) - ) - ); - // @formatter:on - } - - @Bean - JwtDecoder jwtDecoder() { - return NimbusJwtDecoder.withPublicKey(this.key).build(); - } -} diff --git a/samples/boot/oauth2resourceserver-static/src/main/resources/application.yml b/samples/boot/oauth2resourceserver-static/src/main/resources/application.yml deleted file mode 100644 index 123d342ead..0000000000 --- a/samples/boot/oauth2resourceserver-static/src/main/resources/application.yml +++ /dev/null @@ -1,6 +0,0 @@ -spring: - security: - oauth2: - resourceserver: - jwt: - key-value: classpath:simple.pub diff --git a/samples/boot/oauth2resourceserver-static/src/main/resources/simple.pub b/samples/boot/oauth2resourceserver-static/src/main/resources/simple.pub deleted file mode 100644 index a25c08779e..0000000000 --- a/samples/boot/oauth2resourceserver-static/src/main/resources/simple.pub +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd -UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs -HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D -o2kQ+X5xK9cipRgEKwIDAQAB ------END PUBLIC KEY----- - diff --git a/samples/boot/oauth2resourceserver-webflux/README.adoc b/samples/boot/oauth2resourceserver-webflux/README.adoc deleted file mode 100644 index 75c3fd7b41..0000000000 --- a/samples/boot/oauth2resourceserver-webflux/README.adoc +++ /dev/null @@ -1,112 +0,0 @@ -= OAuth 2.0 Resource Server Sample - -This sample demonstrates integrating Resource Server with a mock Authorization Server, though it can be modified to integrate -with your favorite Authorization Server. - -With it, you can run the integration tests or run the application as a stand-alone service to explore how you can -secure your own service with OAuth 2.0 Bearer Tokens using Spring Security. - -== 1. Running the tests - -To run the tests, do: - -```bash -./gradlew integrationTest -``` - -Or import the project into your IDE and run `ServerOAuth2ResourceServerApplicationTests` from there. - -=== What is it doing? - -By default, the tests are pointing at a mock Authorization Server instance. - -The tests are configured with a set of hard-coded tokens originally obtained from the mock Authorization Server, -and each makes a query to the Resource Server with their corresponding token. - -The Resource Server subsquently verifies with the Authorization Server and authorizes the request, returning the phrase - -```bash -Hello, subject! -``` - -where "subject" is the value of the `sub` field in the JWT returned by the Authorization Server. - -== 2. Running the app - -To run as a stand-alone application, do: - -```bash -./gradlew bootRun -``` - -Or import the project into your IDE and run `ServerOAuth2ResourceServerApplication` from there. - -Once it is up, you can use the following token: - -```bash -export TOKEN=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjo0NjgzODA1MTI4fQ.ULEPdHG-MK5GlrTQMhgqcyug2brTIZaJIrahUeq9zaiwUSdW83fJ7W1IDd2Z3n4a25JY2uhEcoV95lMfccHR6y_2DLrNvfta22SumY9PEDF2pido54LXG6edIGgarnUbJdR4rpRe_5oRGVa8gDx8FnuZsNv6StSZHAzw5OsuevSTJ1UbJm4UfX3wiahFOQ2OI6G-r5TB2rQNdiPHuNyzG5yznUqRIZ7-GCoMqHMaC-1epKxiX8gYXRROuUYTtcMNa86wh7OVDmvwVmFioRcR58UWBRoO1XQexTtOQq_t8KYsrPZhb9gkyW8x2bAQF-d0J0EJY8JslaH6n4RBaZISww -``` - -And then make this request: - -```bash -curl -H "Authorization: Bearer $TOKEN" localhost:8080 -``` - -Which will respond with the phrase: - -```bash -Hello, subject! -``` - -where `subject` is the value of the `sub` field in the JWT returned by the Authorization Server. - -Or this: - -```bash -export TOKEN=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0Iiwic2NvcGUiOiJtZXNzYWdlOnJlYWQiLCJleHAiOjQ2ODM4MDUxNDF9.h-j6FKRFdnTdmAueTZCdep45e6DPwqM68ZQ8doIJ1exi9YxAlbWzOwId6Bd0L5YmCmp63gGQgsBUBLzwnZQ8kLUgUOBEC3UzSWGRqMskCY9_k9pX0iomX6IfF3N0PaYs0WPC4hO1s8wfZQ-6hKQ4KigFi13G9LMLdH58PRMK0pKEvs3gCbHJuEPw-K5ORlpdnleUTQIwINafU57cmK3KocTeknPAM_L716sCuSYGvDl6xUTXO7oPdrXhS_EhxLP6KxrpI1uD4Ea_5OWTh7S0Wx5LLDfU6wBG1DowN20d374zepOIEkR-Jnmr_QlR44vmRqS5ncrF-1R0EGcPX49U6A - -curl -H "Authorization: Bearer $TOKEN" localhost:8080/message -``` - -Will respond with: - -```bash -secret message -``` - -== 2. Testing against other Authorization Servers - -_In order to use this sample, your Authorization Server must support JWTs that either use the "scope" or "scp" attribute._ - -To change the sample to point at your Authorization Server, simply find this property in the `application.yml`: - -```yaml -spring: - security: - oauth2: - resourceserver: - jwt: - jwk-set-uri: ${mockwebserver.url}/.well-known/jwks.json -``` - -And change the property to your Authorization Server's JWK set endpoint: - -```yaml -spring: - security: - oauth2: - resourceserver: - jwt: - jwk-set-uri: https://dev-123456.oktapreview.com/oauth2/default/v1/keys -``` - -And then you can run the app the same as before: - -```bash -./gradlew bootRun -``` - -Make sure to obtain valid tokens from your Authorization Server in order to play with the sample Resource Server. -To use the `/` endpoint, any valid token from your Authorization Server will do. -To use the `/message` endpoint, the token should have the `message:read` scope. diff --git a/samples/boot/oauth2resourceserver-webflux/spring-security-samples-boot-oauth2resourceserver-webflux.gradle b/samples/boot/oauth2resourceserver-webflux/spring-security-samples-boot-oauth2resourceserver-webflux.gradle deleted file mode 100644 index 0d92aef8de..0000000000 --- a/samples/boot/oauth2resourceserver-webflux/spring-security-samples-boot-oauth2resourceserver-webflux.gradle +++ /dev/null @@ -1,16 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-oauth2-jose') - compile project(':spring-security-oauth2-client') - compile project(':spring-security-oauth2-resource-server') - - compile 'org.springframework.boot:spring-boot-starter-webflux' - compile 'com.squareup.okhttp3:mockwebserver' - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' - - testCompile 'com.squareup.okhttp3:mockwebserver' -} diff --git a/samples/boot/oauth2resourceserver-webflux/src/integration-test/java/sample/ServerOAuth2ResourceServerApplicationITests.java b/samples/boot/oauth2resourceserver-webflux/src/integration-test/java/sample/ServerOAuth2ResourceServerApplicationITests.java deleted file mode 100644 index 9cbdcf2b36..0000000000 --- a/samples/boot/oauth2resourceserver-webflux/src/integration-test/java/sample/ServerOAuth2ResourceServerApplicationITests.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.HttpHeaders; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.web.reactive.server.WebTestClient; - -import java.util.function.Consumer; - -import static org.hamcrest.Matchers.containsString; - -/** - * @author Rob Winch - * @since 5.1 - */ -@SpringBootTest -@AutoConfigureWebTestClient -@RunWith(SpringJUnit4ClassRunner.class) -public class ServerOAuth2ResourceServerApplicationITests { - - Consumer noScopesToken = (http) -> http.setBearerAuth("eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjo0NjgzODA1MTI4fQ.ULEPdHG-MK5GlrTQMhgqcyug2brTIZaJIrahUeq9zaiwUSdW83fJ7W1IDd2Z3n4a25JY2uhEcoV95lMfccHR6y_2DLrNvfta22SumY9PEDF2pido54LXG6edIGgarnUbJdR4rpRe_5oRGVa8gDx8FnuZsNv6StSZHAzw5OsuevSTJ1UbJm4UfX3wiahFOQ2OI6G-r5TB2rQNdiPHuNyzG5yznUqRIZ7-GCoMqHMaC-1epKxiX8gYXRROuUYTtcMNa86wh7OVDmvwVmFioRcR58UWBRoO1XQexTtOQq_t8KYsrPZhb9gkyW8x2bAQF-d0J0EJY8JslaH6n4RBaZISww"); - Consumer messageReadToken = (http) -> http.setBearerAuth("eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0Iiwic2NvcGUiOiJtZXNzYWdlOnJlYWQiLCJleHAiOjQ2ODM4MDUxNDF9.h-j6FKRFdnTdmAueTZCdep45e6DPwqM68ZQ8doIJ1exi9YxAlbWzOwId6Bd0L5YmCmp63gGQgsBUBLzwnZQ8kLUgUOBEC3UzSWGRqMskCY9_k9pX0iomX6IfF3N0PaYs0WPC4hO1s8wfZQ-6hKQ4KigFi13G9LMLdH58PRMK0pKEvs3gCbHJuEPw-K5ORlpdnleUTQIwINafU57cmK3KocTeknPAM_L716sCuSYGvDl6xUTXO7oPdrXhS_EhxLP6KxrpI1uD4Ea_5OWTh7S0Wx5LLDfU6wBG1DowN20d374zepOIEkR-Jnmr_QlR44vmRqS5ncrF-1R0EGcPX49U6A"); - - @Autowired - private WebTestClient rest; - - - @Test - public void getWhenValidBearerTokenThenAllows() { - - this.rest.get().uri("/") - .headers(this.noScopesToken) - .exchange() - .expectStatus().isOk() - .expectBody(String.class).isEqualTo("Hello, subject!"); - } - - @Test - public void getWhenValidBearerTokenThenScopedRequestsAlsoWork() { - - this.rest.get().uri("/message") - .headers(this.messageReadToken) - .exchange() - .expectStatus().isOk() - .expectBody(String.class).isEqualTo("secret message"); - } - - @Test - public void getWhenInsufficientlyScopedBearerTokenThenDeniesScopedMethodAccess() { - - this.rest.get().uri("/message") - .headers(this.noScopesToken) - .exchange() - .expectStatus().isForbidden() - .expectHeader().value(HttpHeaders.WWW_AUTHENTICATE, containsString("Bearer error=\"insufficient_scope\"")); - } -} diff --git a/samples/boot/oauth2resourceserver-webflux/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java b/samples/boot/oauth2resourceserver-webflux/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java deleted file mode 100644 index 62f91d1a1f..0000000000 --- a/samples/boot/oauth2resourceserver-webflux/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.env; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.boot.SpringApplication; -import org.springframework.core.env.ConfigurableEnvironment; - -/** - * @author Rob Winch - */ -public class MockWebServerEnvironmentPostProcessor - implements EnvironmentPostProcessor, DisposableBean { - - private final MockWebServerPropertySource propertySource = new MockWebServerPropertySource(); - - @Override - public void postProcessEnvironment(ConfigurableEnvironment environment, - SpringApplication application) { - environment.getPropertySources().addFirst(this.propertySource); - } - - @Override - public void destroy() throws Exception { - this.propertySource.destroy(); - } -} diff --git a/samples/boot/oauth2resourceserver-webflux/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java b/samples/boot/oauth2resourceserver-webflux/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java deleted file mode 100644 index 54dc2ca143..0000000000 --- a/samples/boot/oauth2resourceserver-webflux/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.env; - -import okhttp3.mockwebserver.Dispatcher; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.core.env.PropertySource; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; - -import java.io.IOException; - -/** - * @author Rob Winch - */ -public class MockWebServerPropertySource extends PropertySource implements - DisposableBean { - - private static final MockResponse JWKS_RESPONSE = response( - "{\"keys\":[{\"p\":\"2p-ViY7DE9ZrdWQb544m0Jp7Cv03YCSljqfim9pD4ALhObX0OrAznOiowTjwBky9JGffMwDBVSfJSD9TSU7aH2sbbfi0bZLMdekKAuimudXwUqPDxrrg0BCyvCYgLmKjbVT3zcdylWSog93CNTxGDPzauu-oc0XPNKCXnaDpNvE\",\"kty\":\"RSA\",\"q\":\"sP_QYavrpBvSJ86uoKVGj2AGl78CSsAtpf1ybSY5TwUlorXSdqapRbY69Y271b0aMLzlleUn9ZTBO1dlKV2_dw_lPADHVia8z3pxL-8sUhIXLsgj4acchMk4c9YX-sFh07xENnyZ-_TXm3llPLuL67HUfBC2eKe800TmCYVWc9U\",\"d\":\"bn1nFxCQT4KLTHqo8mo9HvHD0cRNRNdWcKNnnEQkCF6tKbt-ILRyQGP8O40axLd7CoNVG9c9p_-g4-2kwCtLJNv_STLtwfpCY7VN5o6-ZIpfTjiW6duoPrLWq64Hm_4LOBQTiZfUPcLhsuJRHbWqakj-kV_YbUyC2Ocf_dd8IAQcSrAU2SCcDebhDCWwRUFvaa9V5eq0851S9goaA-AJz-JXyePH6ZFr8JxmWkWxYZ5kdcMD-sm9ZbxE0CaEk32l4fE4hR-L8x2dDtjWA-ahKCZ091z-gV3HWtR2JOjvxoNRjxUo3UxaGiFJHWNIl0EYUJZu1Cb-5wIlEI7wPx5mwQ\",\"e\":\"AQAB\",\"use\":\"sig\",\"kid\":\"one\",\"qi\":\"qS0OK48M2CIAA6_4Wdw4EbCaAfcTLf5Oy9t5BOF_PFUKqoSpZ6JsT5H0a_4zkjt-oI969v78OTlvBKbmEyKO-KeytzHBAA5CsLmVcz0THrMSg6oXZqu66MPnvWoZN9FEN5TklPOvBFm8Bg1QZ3k-YMVaM--DLvhaYR95_mqaz50\",\"dp\":\"Too2NozLGD1XrXyhabZvy1E0EuaVFj0UHQPDLSpkZ_2g3BK6Art6T0xmE8RYtmqrKIEIdlI3IliAvyvAx_1D7zWTTRaj-xlZyqJFrnXWL7zj8UxT8PkB-r2E-ILZ3NAi1gxIWezlBTZ8M6NfObDFmbTc_3tJkN_raISo8z_ziIE\",\"dq\":\"U0yhSkY5yOsa9YcMoigGVBWSJLpNHtbg5NypjHrPv8OhWbkOSq7WvSstBkFk5AtyFvvfZLMLIkWWxxGzV0t6f1MoxBtttLrYYyCxwihiiGFhLbAdSuZ1wnxcqA9bC7UVECvrQmVTpsMs8UupfHKbQBpZ8OWAqrnuYNNtG4_4Bt0\",\"n\":\"lygtuZj0lJjqOqIWocF8Bb583QDdq-aaFg8PesOp2-EDda6GqCpL-_NZVOflNGX7XIgjsWHcPsQHsV9gWuOzSJ0iEuWvtQ6eGBP5M6m7pccLNZfwUse8Cb4Ngx3XiTlyuqM7pv0LPyppZusfEHVEdeelou7Dy9k0OQ_nJTI3b2E1WBoHC58CJ453lo4gcBm1efURN3LIVc1V9NQY_ESBKVdwqYyoJPEanURLVGRd6cQKn6YrCbbIRHjqAyqOE-z3KmgDJnPriljfR5XhSGyM9eqD9Xpy6zu_MAeMJJfSArp857zLPk-Wf5VP9STAcjyfdBIybMKnwBYr2qHMT675hQ\"}]}", - 200 - ); - - private static final MockResponse NOT_FOUND_RESPONSE = response( - "{ \"message\" : \"This mock authorization server responds to just one request: GET /.well-known/jwks.json.\" }", - 404 - ); - - /** - * Name of the random {@link PropertySource}. - */ - public static final String MOCK_WEB_SERVER_PROPERTY_SOURCE_NAME = "mockwebserver"; - - private static final String NAME = "mockwebserver.url"; - - private static final Log logger = LogFactory.getLog(MockWebServerPropertySource.class); - - private boolean started; - - public MockWebServerPropertySource() { - super(MOCK_WEB_SERVER_PROPERTY_SOURCE_NAME, new MockWebServer()); - } - - @Override - public Object getProperty(String name) { - if (!name.equals(NAME)) { - return null; - } - if (logger.isTraceEnabled()) { - logger.trace("Looking up the url for '" + name + "'"); - } - String url = getUrl(); - return url; - } - - @Override - public void destroy() throws Exception { - getSource().shutdown(); - } - - /** - * Get's the URL (i.e. "http://localhost:123456") - * @return - */ - private String getUrl() { - MockWebServer mockWebServer = getSource(); - if (!this.started) { - intializeMockWebServer(mockWebServer); - } - String url = mockWebServer.url("").url().toExternalForm(); - return url.substring(0, url.length() - 1); - } - - private void intializeMockWebServer(MockWebServer mockWebServer) { - Dispatcher dispatcher = new Dispatcher() { - @Override - public MockResponse dispatch(RecordedRequest request) { - if ("/.well-known/jwks.json".equals(request.getPath())) { - return JWKS_RESPONSE; - } - - return NOT_FOUND_RESPONSE; - } - }; - - mockWebServer.setDispatcher(dispatcher); - try { - mockWebServer.start(); - this.started = true; - } catch (IOException e) { - throw new RuntimeException("Could not start " + mockWebServer, e); - } - } - - private static MockResponse response(String body, int status) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setResponseCode(status) - .setBody(body); - } - -} diff --git a/samples/boot/oauth2resourceserver-webflux/src/main/java/org/springframework/boot/env/package-info.java b/samples/boot/oauth2resourceserver-webflux/src/main/java/org/springframework/boot/env/package-info.java deleted file mode 100644 index 0226037822..0000000000 --- a/samples/boot/oauth2resourceserver-webflux/src/main/java/org/springframework/boot/env/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * This provides integration of a {@link okhttp3.mockwebserver.MockWebServer} and the - * {@link org.springframework.core.env.Environment} - * @author Rob Winch - */ -package org.springframework.boot.env; diff --git a/samples/boot/oauth2resourceserver-webflux/src/main/java/sample/OAuth2ResourceServerController.java b/samples/boot/oauth2resourceserver-webflux/src/main/java/sample/OAuth2ResourceServerController.java deleted file mode 100644 index ea34b99e20..0000000000 --- a/samples/boot/oauth2resourceserver-webflux/src/main/java/sample/OAuth2ResourceServerController.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.oauth2.jwt.Jwt; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author Josh Cummings - */ -@RestController -public class OAuth2ResourceServerController { - - @GetMapping("/") - public String index(@AuthenticationPrincipal Jwt jwt) { - return String.format("Hello, %s!", jwt.getSubject()); - } - - @GetMapping("/message") - public String message() { - return "secret message"; - } - - @PostMapping("/message") - public String createMessage(@RequestBody String message) { - return String.format("Message was created. Content: %s", message); - } -} diff --git a/samples/boot/oauth2resourceserver-webflux/src/main/java/sample/SecurityConfig.java b/samples/boot/oauth2resourceserver-webflux/src/main/java/sample/SecurityConfig.java deleted file mode 100644 index d4f6429b51..0000000000 --- a/samples/boot/oauth2resourceserver-webflux/src/main/java/sample/SecurityConfig.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpMethod; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; -import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.web.server.SecurityWebFilterChain; - -import static org.springframework.security.config.Customizer.withDefaults; - -/** - * @author Rob Winch - * @since 5.1 - */ -@EnableWebFluxSecurity -public class SecurityConfig { - - @Bean - SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { - http - .authorizeExchange((exchanges) -> - exchanges - .pathMatchers(HttpMethod.GET, "/message/**").hasAuthority("SCOPE_message:read") - .pathMatchers(HttpMethod.POST, "/message/**").hasAuthority("SCOPE_message:write") - .anyExchange().authenticated() - ) - .oauth2ResourceServer((oauth2ResourceServer) -> - oauth2ResourceServer - .jwt(withDefaults()) - ); - return http.build(); - } -} diff --git a/samples/boot/oauth2resourceserver-webflux/src/main/java/sample/ServerOAuth2ResourceServerApplication.java b/samples/boot/oauth2resourceserver-webflux/src/main/java/sample/ServerOAuth2ResourceServerApplication.java deleted file mode 100644 index c3e3575e26..0000000000 --- a/samples/boot/oauth2resourceserver-webflux/src/main/java/sample/ServerOAuth2ResourceServerApplication.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Rob Winch - */ -@SpringBootApplication -public class ServerOAuth2ResourceServerApplication { - - public static void main(String[] args) { - SpringApplication.run(ServerOAuth2ResourceServerApplication.class, args); - } -} diff --git a/samples/boot/oauth2resourceserver-webflux/src/main/resources/META-INF/spring.factories b/samples/boot/oauth2resourceserver-webflux/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 37b447c970..0000000000 --- a/samples/boot/oauth2resourceserver-webflux/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1 +0,0 @@ -org.springframework.boot.env.EnvironmentPostProcessor=org.springframework.boot.env.MockWebServerEnvironmentPostProcessor diff --git a/samples/boot/oauth2resourceserver-webflux/src/main/resources/application.yml b/samples/boot/oauth2resourceserver-webflux/src/main/resources/application.yml deleted file mode 100644 index 2a6d127d3f..0000000000 --- a/samples/boot/oauth2resourceserver-webflux/src/main/resources/application.yml +++ /dev/null @@ -1,6 +0,0 @@ -spring: - security: - oauth2: - resourceserver: - jwt: - jwk-set-uri: ${mockwebserver.url}/.well-known/jwks.json diff --git a/samples/boot/oauth2resourceserver-webflux/src/test/java/sample/OAuth2ResourceServerControllerTests.java b/samples/boot/oauth2resourceserver-webflux/src/test/java/sample/OAuth2ResourceServerControllerTests.java deleted file mode 100644 index 8fc72574f1..0000000000 --- a/samples/boot/oauth2resourceserver-webflux/src/test/java/sample/OAuth2ResourceServerControllerTests.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; -import reactor.core.publisher.Mono; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.context.annotation.Import; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.oauth2.jwt.Jwt; -import org.springframework.security.oauth2.jwt.ReactiveJwtDecoder; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; - -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.when; -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockJwt; - -/** - * @author Josh Cummings - */ -@RunWith(SpringRunner.class) -@WebFluxTest(OAuth2ResourceServerController.class) -@Import(SecurityConfig.class) -public class OAuth2ResourceServerControllerTests { - - @Autowired - WebTestClient rest; - - @MockBean - ReactiveJwtDecoder jwtDecoder; - - @Test - public void indexGreetsAuthenticatedUser() { - this.rest.mutateWith(mockJwt().jwt((jwt) -> jwt.subject("test-subject"))) - .get().uri("/").exchange() - .expectBody(String.class).isEqualTo("Hello, test-subject!"); - } - - @Test - public void messageCanBeReadWithScopeMessageReadAuthority() { - this.rest.mutateWith(mockJwt().jwt((jwt) -> jwt.claim("scope", "message:read"))) - .get().uri("/message").exchange() - .expectBody(String.class).isEqualTo("secret message"); - - this.rest.mutateWith(mockJwt().authorities(new SimpleGrantedAuthority("SCOPE_message:read"))) - .get().uri("/message").exchange() - .expectBody(String.class).isEqualTo("secret message"); - } - - @Test - public void messageCanNotBeReadWithoutScopeMessageReadAuthority() { - this.rest.mutateWith(mockJwt()) - .get().uri("/message").exchange() - .expectStatus().isForbidden(); - } - - @Test - public void messageCanNotBeCreatedWithoutAnyScope() { - Jwt jwt = jwt().claim("scope", "").build(); - when(this.jwtDecoder.decode(anyString())).thenReturn(Mono.just(jwt)); - this.rest.post().uri("/message") - .headers((headers) -> headers.setBearerAuth(jwt.getTokenValue())) - .syncBody("Hello message").exchange() - .expectStatus().isForbidden(); - } - - @Test - public void messageCanNotBeCreatedWithScopeMessageReadAuthority() { - Jwt jwt = jwt().claim("scope", "message:read").build(); - when(this.jwtDecoder.decode(anyString())).thenReturn(Mono.just(jwt)); - this.rest.post().uri("/message") - .headers((headers) -> headers.setBearerAuth(jwt.getTokenValue())) - .syncBody("Hello message").exchange() - .expectStatus().isForbidden(); - } - - @Test - public void messageCanBeCreatedWithScopeMessageWriteAuthority() { - Jwt jwt = jwt().claim("scope", "message:write").build(); - when(this.jwtDecoder.decode(anyString())).thenReturn(Mono.just(jwt)); - this.rest.post().uri("/message") - .headers((headers) -> headers.setBearerAuth(jwt.getTokenValue())) - .syncBody("Hello message").exchange() - .expectStatus().isOk() - .expectBody(String.class).isEqualTo("Message was created. Content: Hello message"); - } - - private Jwt.Builder jwt() { - return Jwt.withTokenValue("token").header("alg", "none"); - } -} diff --git a/samples/boot/oauth2resourceserver/README.adoc b/samples/boot/oauth2resourceserver/README.adoc deleted file mode 100644 index a82747004f..0000000000 --- a/samples/boot/oauth2resourceserver/README.adoc +++ /dev/null @@ -1,126 +0,0 @@ -= OAuth 2.0 Resource Server Sample - -This sample demonstrates integrating Resource Server with a mock Authorization Server, though it can be modified to integrate -with your favorite Authorization Server. - -With it, you can run the integration tests or run the application as a stand-alone service to explore how you can -secure your own service with OAuth 2.0 Bearer Tokens using Spring Security. - -== 1. Running the tests - -To run the tests, do: - -```bash -./gradlew integrationTest -``` - -Or import the project into your IDE and run `OAuth2ResourceServerApplicationTests` from there. - -=== What is it doing? - -By default, the tests are pointing at a mock Authorization Server instance. - -The tests are configured with a set of hard-coded tokens originally obtained from the mock Authorization Server, -and each makes a query to the Resource Server with their corresponding token. - -The Resource Server subsquently verifies with the Authorization Server and authorizes the request, returning the phrase - -```bash -Hello, subject! -``` - -where "subject" is the value of the `sub` field in the JWT returned by the Authorization Server. - -== 2. Running the app - -To run as a stand-alone application, do: - -```bash -./gradlew bootRun -``` - -Or import the project into your IDE and run `OAuth2ResourceServerApplication` from there. - -Once it is up, you can use the following token: - -```bash -export TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjoyMTY0MjQ1ODgwLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiMDFkOThlZWEtNjc0MC00OGRlLTk4ODAtYzM5ZjgyMGZiNzVlIiwiY2xpZW50X2lkIjoibm9zY29wZXMiLCJzY29wZSI6WyJub25lIl19.VOzgGLOUuQ_R2Ur1Ke41VaobddhKgUZgto7Y3AGxst7SuxLQ4LgWwdSSDRx-jRvypjsCgYPbjAYLhn9nCbfwtCitkymUKUNKdebvVAI0y8YvliWTL5S-GiJD9dN8SSsXUla9A4xB_9Mt5JAlRpQotQSCLojVSKQmjhMpQWmYAlKVjnlImoRwQFPI4w3Ijn4G4EMTKWUYRfrD0-WNT9ZYWBeza6QgV6sraP7ToRB3eQLy2p04cU40X-RHLeYCsMBfxsMMh89CJff-9tn7VDKi1hAGc_Lp9yS9ZaItJuFJTjf8S_vsjVB1nBhvdS_6IED_m_fOU52KiGSO2qL6shxHvg -``` - -And then make this request: - -```bash -curl -H "Authorization: Bearer $TOKEN" localhost:8080 -``` - -Which will respond with the phrase: - -```bash -Hello, subject! -``` - -where `subject` is the value of the `sub` field in the JWT returned by the Authorization Server. - -Or this to make a GET request to /messages: - -```bash -export TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjoyMTY0MjQ1NjQ4LCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiY2I1ZGMwNDYtMDkyMi00ZGJmLWE5MzAtOGI2M2FhZTYzZjk2IiwiY2xpZW50X2lkIjoicmVhZGVyIiwic2NvcGUiOlsibWVzc2FnZTpyZWFkIl19.Pre2ksnMiOGYWQtuIgHB0i3uTnNzD0SMFM34iyQJHK5RLlSjge08s9qHdx6uv5cZ4gZm_cB1D6f4-fLx76bCblK6mVcabbR74w_eCdSBXNXuqG-HNrOYYmmx5iJtdwx5fXPmF8TyVzsq_LvRm_LN4lWNYquT4y36Tox6ZD3feYxXvHQ3XyZn9mVKnlzv-GCwkBohCR3yPow5uVmr04qh_al52VIwKMrvJBr44igr4fTZmzwRAZmQw5rZeyep0b4nsCjadNcndHtMtYKNVuG5zbDLsB7GGvilcI9TDDnUXtwthB_3iq32DAd9x8wJmJ5K8gmX6GjZFtYzKk_zEboXoQ - -curl -H "Authorization: Bearer $TOKEN" localhost:8080/message -``` - -Will respond with: - -```bash -secret message -``` - -In order to make a POST request to /message, you can use the following request: - -```bash -export TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjoyMTY0MjQzOTA0LCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiZGI4ZjgwMzQtM2VlNy00NjBjLTk3NTEtMDJiMDA1OWI5NzA4IiwiY2xpZW50X2lkIjoid3JpdGVyIiwic2NvcGUiOlsibWVzc2FnZTp3cml0ZSJdfQ.USvpx_ntKXtchLmc93auJq0qSav6vLm4B7ItPzhrDH2xmogBP35eKeklwXK5GCb7ck1aKJV5SpguBlTCz0bZC1zAWKB6gyFIqedALPAran5QR-8WpGfl0wFqds7d8Jw3xmpUUBduRLab9hkeAhgoVgxevc8d6ITM7kRnHo5wT3VzvBU8DquedVXm5fbBnRPgG4_jOWJKbqYpqaR2z2TnZRWh3CqL82Orh1Ww1dJYF_fae1dTVV4tvN5iSndYcGxMoBaiw3kRRi6EyNxnXnt1pFtZqc1f6D9x4AHiri8_vpBp2vwG5OfQD5-rrleP_XlIB3rNQT7tu3fiqu4vUzQaEg - -curl -H "Authorization: Bearer $TOKEN" -d "my message" localhost:8080/message -``` - -Will respond this: - -```bash -Message was created. Content: my message -``` - -== 2. Testing against other Authorization Servers - -_In order to use this sample, your Authorization Server must support JWTs that either use the "scope" or "scp" attribute._ - -To change the sample to point at your Authorization Server, simply find this property in the `application.yml`: - -```yaml -spring: - security: - oauth2: - resourceserver: - jwt: - jwk-set-uri: ${mockwebserver.url}/.well-known/jwks.json -``` - -And change the property to your Authorization Server's JWK set endpoint: - -```yaml -spring: - security: - oauth2: - resourceserver: - jwt: - jwk-set-uri: https://dev-123456.oktapreview.com/oauth2/default/v1/keys -``` - -And then you can run the app the same as before: - -```bash -./gradlew bootRun -``` - -Make sure to obtain valid tokens from your Authorization Server in order to play with the sample Resource Server. -To use the `/` endpoint, any valid token from your Authorization Server will do. -To use the `/message` endpoint, the token should have the `message:read` scope. diff --git a/samples/boot/oauth2resourceserver/spring-security-samples-boot-oauth2resourceserver.gradle b/samples/boot/oauth2resourceserver/spring-security-samples-boot-oauth2resourceserver.gradle deleted file mode 100644 index 2135bb0af6..0000000000 --- a/samples/boot/oauth2resourceserver/spring-security-samples-boot-oauth2resourceserver.gradle +++ /dev/null @@ -1,13 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-oauth2-jose') - compile project(':spring-security-oauth2-resource-server') - - compile 'org.springframework.boot:spring-boot-starter-web' - compile 'com.squareup.okhttp3:mockwebserver' - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/oauth2resourceserver/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java b/samples/boot/oauth2resourceserver/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java deleted file mode 100644 index bb7de58665..0000000000 --- a/samples/boot/oauth2resourceserver/src/integration-test/java/sample/OAuth2ResourceServerApplicationITests.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; - -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.HttpHeaders; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.request.RequestPostProcessor; - -import static org.hamcrest.Matchers.containsString; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -/** - * Integration tests for {@link OAuth2ResourceServerApplication} - * - * @author Josh Cummings - */ -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -@ActiveProfiles("test") -public class OAuth2ResourceServerApplicationITests { - - String noScopesToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjoyMTY0MjQ1ODgwLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiMDFkOThlZWEtNjc0MC00OGRlLTk4ODAtYzM5ZjgyMGZiNzVlIiwiY2xpZW50X2lkIjoibm9zY29wZXMiLCJzY29wZSI6WyJub25lIl19.VOzgGLOUuQ_R2Ur1Ke41VaobddhKgUZgto7Y3AGxst7SuxLQ4LgWwdSSDRx-jRvypjsCgYPbjAYLhn9nCbfwtCitkymUKUNKdebvVAI0y8YvliWTL5S-GiJD9dN8SSsXUla9A4xB_9Mt5JAlRpQotQSCLojVSKQmjhMpQWmYAlKVjnlImoRwQFPI4w3Ijn4G4EMTKWUYRfrD0-WNT9ZYWBeza6QgV6sraP7ToRB3eQLy2p04cU40X-RHLeYCsMBfxsMMh89CJff-9tn7VDKi1hAGc_Lp9yS9ZaItJuFJTjf8S_vsjVB1nBhvdS_6IED_m_fOU52KiGSO2qL6shxHvg"; - String messageReadToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjoyMTY0MjQ1NjQ4LCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiY2I1ZGMwNDYtMDkyMi00ZGJmLWE5MzAtOGI2M2FhZTYzZjk2IiwiY2xpZW50X2lkIjoicmVhZGVyIiwic2NvcGUiOlsibWVzc2FnZTpyZWFkIl19.Pre2ksnMiOGYWQtuIgHB0i3uTnNzD0SMFM34iyQJHK5RLlSjge08s9qHdx6uv5cZ4gZm_cB1D6f4-fLx76bCblK6mVcabbR74w_eCdSBXNXuqG-HNrOYYmmx5iJtdwx5fXPmF8TyVzsq_LvRm_LN4lWNYquT4y36Tox6ZD3feYxXvHQ3XyZn9mVKnlzv-GCwkBohCR3yPow5uVmr04qh_al52VIwKMrvJBr44igr4fTZmzwRAZmQw5rZeyep0b4nsCjadNcndHtMtYKNVuG5zbDLsB7GGvilcI9TDDnUXtwthB_3iq32DAd9x8wJmJ5K8gmX6GjZFtYzKk_zEboXoQ"; - String messageWriteToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJzdWJqZWN0IiwiZXhwIjoyMTY0MjQzOTA0LCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiZGI4ZjgwMzQtM2VlNy00NjBjLTk3NTEtMDJiMDA1OWI5NzA4IiwiY2xpZW50X2lkIjoid3JpdGVyIiwic2NvcGUiOlsibWVzc2FnZTp3cml0ZSJdfQ.USvpx_ntKXtchLmc93auJq0qSav6vLm4B7ItPzhrDH2xmogBP35eKeklwXK5GCb7ck1aKJV5SpguBlTCz0bZC1zAWKB6gyFIqedALPAran5QR-8WpGfl0wFqds7d8Jw3xmpUUBduRLab9hkeAhgoVgxevc8d6ITM7kRnHo5wT3VzvBU8DquedVXm5fbBnRPgG4_jOWJKbqYpqaR2z2TnZRWh3CqL82Orh1Ww1dJYF_fae1dTVV4tvN5iSndYcGxMoBaiw3kRRi6EyNxnXnt1pFtZqc1f6D9x4AHiri8_vpBp2vwG5OfQD5-rrleP_XlIB3rNQT7tu3fiqu4vUzQaEg"; - - @Autowired - MockMvc mvc; - - @Test - public void performWhenValidBearerTokenThenAllows() - throws Exception { - - this.mvc.perform(get("/").with(bearerToken(this.noScopesToken))) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("Hello, subject!"))); - } - - @Test - public void performWhenValidBearerTokenThenScopedRequestsAlsoWork() - throws Exception { - - this.mvc.perform(get("/message").with(bearerToken(this.messageReadToken))) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("secret message"))); - } - - @Test - public void performWhenInsufficientlyScopedBearerTokenThenDeniesScopedMethodAccess() - throws Exception { - - this.mvc.perform(get("/message").with(bearerToken(this.noScopesToken))) - .andExpect(status().isForbidden()) - .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, - containsString("Bearer error=\"insufficient_scope\""))); - } - - @Test - public void performPostWhenValidBearerTokenThenScopedRequestsAlsoWork() - throws Exception { - - this.mvc.perform(post("/message").content("example message") - .with(bearerToken(this.messageWriteToken))) - .andExpect(status().isOk()) - .andExpect(content().string(containsString("Message was created"))); - } - - @Test - public void performPostWhenInsufficientlyScopedBearerTokenThenDeniesScopedMethodAccess() - throws Exception { - - this.mvc.perform(post("/message").content("Example message") - .with(bearerToken(this.messageReadToken))) - .andExpect(status().isForbidden()) - .andExpect(header().string(HttpHeaders.WWW_AUTHENTICATE, - containsString("Bearer error=\"insufficient_scope\""))); - } - - private static class BearerTokenRequestPostProcessor implements RequestPostProcessor { - private String token; - - BearerTokenRequestPostProcessor(String token) { - this.token = token; - } - - @Override - public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) { - request.addHeader("Authorization", "Bearer " + this.token); - return request; - } - } - - private static BearerTokenRequestPostProcessor bearerToken(String token) { - return new BearerTokenRequestPostProcessor(token); - } -} diff --git a/samples/boot/oauth2resourceserver/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java b/samples/boot/oauth2resourceserver/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java deleted file mode 100644 index 62f91d1a1f..0000000000 --- a/samples/boot/oauth2resourceserver/src/main/java/org/springframework/boot/env/MockWebServerEnvironmentPostProcessor.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.env; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.boot.SpringApplication; -import org.springframework.core.env.ConfigurableEnvironment; - -/** - * @author Rob Winch - */ -public class MockWebServerEnvironmentPostProcessor - implements EnvironmentPostProcessor, DisposableBean { - - private final MockWebServerPropertySource propertySource = new MockWebServerPropertySource(); - - @Override - public void postProcessEnvironment(ConfigurableEnvironment environment, - SpringApplication application) { - environment.getPropertySources().addFirst(this.propertySource); - } - - @Override - public void destroy() throws Exception { - this.propertySource.destroy(); - } -} diff --git a/samples/boot/oauth2resourceserver/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java b/samples/boot/oauth2resourceserver/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java deleted file mode 100644 index b90ad29b91..0000000000 --- a/samples/boot/oauth2resourceserver/src/main/java/org/springframework/boot/env/MockWebServerPropertySource.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.boot.env; - -import okhttp3.mockwebserver.Dispatcher; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.core.env.PropertySource; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; - -import java.io.IOException; - -/** - * @author Rob Winch - */ -public class MockWebServerPropertySource extends PropertySource implements - DisposableBean { - - private static final MockResponse JWKS_RESPONSE = response( - "{ \"keys\": [ { \"kty\": \"RSA\", \"e\": \"AQAB\", \"n\": \"jvBtqsGCOmnYzwe_-HvgOqlKk6HPiLEzS6uCCcnVkFXrhnkPMZ-uQXTR0u-7ZklF0XC7-AMW8FQDOJS1T7IyJpCyeU4lS8RIf_Z8RX51gPGnQWkRvNw61RfiSuSA45LR5NrFTAAGoXUca_lZnbqnl0td-6hBDVeHYkkpAsSck1NPhlcsn-Pvc2Vleui_Iy1U2mzZCM1Vx6Dy7x9IeP_rTNtDhULDMFbB_JYs-Dg6Zd5Ounb3mP57tBGhLYN7zJkN1AAaBYkElsc4GUsGsUWKqgteQSXZorpf6HdSJsQMZBDd7xG8zDDJ28hGjJSgWBndRGSzQEYU09Xbtzk-8khPuw\" } ] }", - 200 - ); - - private static final MockResponse NOT_FOUND_RESPONSE = response( - "{ \"message\" : \"This mock authorization server responds to just one request: GET /.well-known/jwks.json.\" }", - 404 - ); - - /** - * Name of the random {@link PropertySource}. - */ - public static final String MOCK_WEB_SERVER_PROPERTY_SOURCE_NAME = "mockwebserver"; - - private static final String NAME = "mockwebserver.url"; - - private static final Log logger = LogFactory.getLog(MockWebServerPropertySource.class); - - private boolean started; - - public MockWebServerPropertySource() { - super(MOCK_WEB_SERVER_PROPERTY_SOURCE_NAME, new MockWebServer()); - } - - @Override - public Object getProperty(String name) { - if (!name.equals(NAME)) { - return null; - } - if (logger.isTraceEnabled()) { - logger.trace("Looking up the url for '" + name + "'"); - } - String url = getUrl(); - return url; - } - - @Override - public void destroy() throws Exception { - getSource().shutdown(); - } - - /** - * Get's the URL (i.e. "http://localhost:123456") - * @return - */ - private String getUrl() { - MockWebServer mockWebServer = getSource(); - if (!this.started) { - intializeMockWebServer(mockWebServer); - } - String url = mockWebServer.url("").url().toExternalForm(); - return url.substring(0, url.length() - 1); - } - - private void intializeMockWebServer(MockWebServer mockWebServer) { - Dispatcher dispatcher = new Dispatcher() { - @Override - public MockResponse dispatch(RecordedRequest request) { - if ("/.well-known/jwks.json".equals(request.getPath())) { - return JWKS_RESPONSE; - } - - return NOT_FOUND_RESPONSE; - } - }; - - mockWebServer.setDispatcher(dispatcher); - try { - mockWebServer.start(); - this.started = true; - } catch (IOException e) { - throw new RuntimeException("Could not start " + mockWebServer, e); - } - } - - private static MockResponse response(String body, int status) { - return new MockResponse() - .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .setResponseCode(status) - .setBody(body); - } - -} diff --git a/samples/boot/oauth2resourceserver/src/main/java/org/springframework/boot/env/package-info.java b/samples/boot/oauth2resourceserver/src/main/java/org/springframework/boot/env/package-info.java deleted file mode 100644 index 0226037822..0000000000 --- a/samples/boot/oauth2resourceserver/src/main/java/org/springframework/boot/env/package-info.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * This provides integration of a {@link okhttp3.mockwebserver.MockWebServer} and the - * {@link org.springframework.core.env.Environment} - * @author Rob Winch - */ -package org.springframework.boot.env; diff --git a/samples/boot/oauth2resourceserver/src/main/java/sample/OAuth2ResourceServerApplication.java b/samples/boot/oauth2resourceserver/src/main/java/sample/OAuth2ResourceServerApplication.java deleted file mode 100644 index a0841c00f3..0000000000 --- a/samples/boot/oauth2resourceserver/src/main/java/sample/OAuth2ResourceServerApplication.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Josh Cummings - */ -@SpringBootApplication -public class OAuth2ResourceServerApplication { - - public static void main(String[] args) { - SpringApplication.run(OAuth2ResourceServerApplication.class, args); - } -} diff --git a/samples/boot/oauth2resourceserver/src/main/java/sample/OAuth2ResourceServerController.java b/samples/boot/oauth2resourceserver/src/main/java/sample/OAuth2ResourceServerController.java deleted file mode 100644 index c761078dd8..0000000000 --- a/samples/boot/oauth2resourceserver/src/main/java/sample/OAuth2ResourceServerController.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.oauth2.jwt.Jwt; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -/** - * @author Josh Cummings - */ -@RestController -public class OAuth2ResourceServerController { - - @GetMapping("/") - public String index(@AuthenticationPrincipal Jwt jwt) { - return String.format("Hello, %s!", jwt.getSubject()); - } - - @GetMapping("/message") - public String message() { - return "secret message"; - } - - @PostMapping("/message") - public String createMessage(@RequestBody String message) { - return String.format("Message was created. Content: %s", message); - } -} diff --git a/samples/boot/oauth2resourceserver/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java b/samples/boot/oauth2resourceserver/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java deleted file mode 100644 index d7e157cfc6..0000000000 --- a/samples/boot/oauth2resourceserver/src/main/java/sample/OAuth2ResourceServerSecurityConfiguration.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpMethod; -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.WebSecurityConfigurerAdapter; -import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer; -import org.springframework.security.oauth2.jwt.JwtDecoder; -import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; - -/** - * @author Josh Cummings - */ -@EnableWebSecurity -public class OAuth2ResourceServerSecurityConfiguration extends WebSecurityConfigurerAdapter { - - @Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}") String jwkSetUri; - - @Override - protected void configure(HttpSecurity http) throws Exception { - // @formatter:off - http - .authorizeRequests((authorizeRequests) -> - authorizeRequests - .antMatchers(HttpMethod.GET, "/message/**").hasAuthority("SCOPE_message:read") - .antMatchers(HttpMethod.POST, "/message/**").hasAuthority("SCOPE_message:write") - .anyRequest().authenticated() - ) - .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt); - // @formatter:on - } - - @Bean - JwtDecoder jwtDecoder() { - return NimbusJwtDecoder.withJwkSetUri(this.jwkSetUri).build(); - } -} diff --git a/samples/boot/oauth2resourceserver/src/main/resources/META-INF/spring.factories b/samples/boot/oauth2resourceserver/src/main/resources/META-INF/spring.factories deleted file mode 100644 index 37b447c970..0000000000 --- a/samples/boot/oauth2resourceserver/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1 +0,0 @@ -org.springframework.boot.env.EnvironmentPostProcessor=org.springframework.boot.env.MockWebServerEnvironmentPostProcessor diff --git a/samples/boot/oauth2resourceserver/src/main/resources/application.yml b/samples/boot/oauth2resourceserver/src/main/resources/application.yml deleted file mode 100644 index 2a6d127d3f..0000000000 --- a/samples/boot/oauth2resourceserver/src/main/resources/application.yml +++ /dev/null @@ -1,6 +0,0 @@ -spring: - security: - oauth2: - resourceserver: - jwt: - jwk-set-uri: ${mockwebserver.url}/.well-known/jwks.json diff --git a/samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTests.java b/samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTests.java deleted file mode 100644 index 565212b073..0000000000 --- a/samples/boot/oauth2resourceserver/src/test/java/sample/OAuth2ResourceServerControllerTests.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; - -import static org.hamcrest.CoreMatchers.is; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -/** - * - * @author JĂ©rĂŽme Wacongne <ch4mp@c4-soft.com> - * @author Josh Cummings - * @since 5.2.0 - * - */ -@RunWith(SpringRunner.class) -@WebMvcTest(OAuth2ResourceServerController.class) -public class OAuth2ResourceServerControllerTests { - - @Autowired - MockMvc mockMvc; - - @Test - public void indexGreetsAuthenticatedUser() throws Exception { - mockMvc.perform(get("/").with(jwt().jwt((jwt) -> jwt.subject("ch4mpy")))) - .andExpect(content().string(is("Hello, ch4mpy!"))); - } - - @Test - public void messageCanBeReadWithScopeMessageReadAuthority() throws Exception { - mockMvc.perform(get("/message").with(jwt().jwt((jwt) -> jwt.claim("scope", "message:read")))) - .andExpect(content().string(is("secret message"))); - - mockMvc.perform(get("/message") - .with(jwt().authorities(new SimpleGrantedAuthority(("SCOPE_message:read"))))) - .andExpect(content().string(is("secret message"))); - } - - @Test - public void messageCanNotBeReadWithoutScopeMessageReadAuthority() throws Exception { - mockMvc.perform(get("/message").with(jwt())) - .andExpect(status().isForbidden()); - } - - @Test - public void messageCanNotBeCreatedWithoutAnyScope() throws Exception { - mockMvc.perform(post("/message") - .content("Hello message") - .with(jwt())) - .andExpect(status().isForbidden()); - } - - @Test - public void messageCanNotBeCreatedWithScopeMessageReadAuthority() throws Exception { - mockMvc.perform(post("/message") - .content("Hello message") - .with(jwt().jwt((jwt) -> jwt.claim("scope", "message:read")))) - .andExpect(status().isForbidden()); - } - - @Test - public void messageCanBeCreatedWithScopeMessageWriteAuthority() - throws Exception { - mockMvc.perform(post("/message") - .content("Hello message") - .with(jwt().jwt((jwt) -> jwt.claim("scope", "message:write")))) - .andExpect(status().isOk()) - .andExpect(content().string(is("Message was created. Content: Hello message"))); - } -} diff --git a/samples/boot/oauth2webclient-webflux/README.adoc b/samples/boot/oauth2webclient-webflux/README.adoc deleted file mode 100644 index ea984aa684..0000000000 --- a/samples/boot/oauth2webclient-webflux/README.adoc +++ /dev/null @@ -1,63 +0,0 @@ -= OAuth 2.0 WebClient (WebFlux) Sample - -== GitHub Repositories - -This guide provides instructions on setting up the sample application, which leverages WebClient OAuth2 integration to display a list of public GitHub repositories that are accessible to the authenticated user. - -This includes repositories owned by the authenticated user, repositories where the authenticated user is a collaborator, and repositories that the authenticated user has access to through an organization membership. - -The following sections provide detailed steps for setting up the sample and covers the following topics: - -* <> -* <> -* <> - -[[github-register-application]] -=== Register OAuth application - -To use GitHub's OAuth 2.0 authorization system, you must https://github.com/settings/applications/new[Register a new OAuth application]. - -When registering the OAuth application, ensure the *Authorization callback URL* is set to `http://localhost:8080/login/oauth2/code/client-id`. - -The Authorization callback URL (redirect URI) is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with GitHub and have granted access to the OAuth application on the _Authorize application_ page. - -[[github-application-config]] -=== Configure application.yml - -Now that you have a new OAuth application with GitHub, you need to configure the sample to use the OAuth application for the _authorization code grant flow_. -To do so: - -. Go to `application.yml` and set the following configuration: -+ -[source,yaml] ----- -spring: - security: - oauth2: - client: - registration: <1> - client-id: <2> - client-id: replace-with-client-id - client-secret: replace-with-client-secret - provider: github - scope: read:user,public_repo ----- -+ -.OAuth Client properties -==== -<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties. -<2> Following the base property prefix is the ID for the `ClientRegistration`, which is github. -==== - -. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials you created earlier. - -[[github-boot-application]] -=== Boot up the application - -Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`. -You are then redirected to the default _auto-generated_ form login page. -Log in using *'user'* (username) and *'password'* (password) or click the link to authenticate with GitHub and then you'll be redirected to GitHub for authentication. - -After authenticating with your GitHub credentials, the next page presented to you is "Authorize application". -This page will ask you to *Authorize* the application you created in the previous step. -Click _Authorize application_ to allow the OAuth application to access and display your public repository information. diff --git a/samples/boot/oauth2webclient-webflux/spring-security-samples-boot-oauth2webclient-webflux.gradle b/samples/boot/oauth2webclient-webflux/spring-security-samples-boot-oauth2webclient-webflux.gradle deleted file mode 100644 index 286f80a581..0000000000 --- a/samples/boot/oauth2webclient-webflux/spring-security-samples-boot-oauth2webclient-webflux.gradle +++ /dev/null @@ -1,15 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-oauth2-client') - compile project(':spring-security-oauth2-jose') - compile 'org.springframework.boot:spring-boot-starter-thymeleaf' - compile 'org.springframework.boot:spring-boot-starter-webflux' - compile 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' - compile 'io.projectreactor.netty:reactor-netty' - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' - testCompile 'com.squareup.okhttp3:mockwebserver' -} diff --git a/samples/boot/oauth2webclient-webflux/src/main/java/sample/OAuth2WebClientWebFluxApplication.java b/samples/boot/oauth2webclient-webflux/src/main/java/sample/OAuth2WebClientWebFluxApplication.java deleted file mode 100644 index cdd6416f93..0000000000 --- a/samples/boot/oauth2webclient-webflux/src/main/java/sample/OAuth2WebClientWebFluxApplication.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Joe Grandja - */ -@SpringBootApplication -public class OAuth2WebClientWebFluxApplication { - - public static void main(String[] args) { - SpringApplication.run(OAuth2WebClientWebFluxApplication.class, args); - } -} diff --git a/samples/boot/oauth2webclient-webflux/src/main/java/sample/config/SecurityConfig.java b/samples/boot/oauth2webclient-webflux/src/main/java/sample/config/SecurityConfig.java deleted file mode 100644 index 33fb8b7867..0000000000 --- a/samples/boot/oauth2webclient-webflux/src/main/java/sample/config/SecurityConfig.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.config; - -import org.springframework.context.annotation.Bean; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; -import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.web.server.SecurityWebFilterChain; - -import static org.springframework.security.config.Customizer.withDefaults; - -/** - * @author Rob Winch - */ -@EnableWebFluxSecurity -public class SecurityConfig { - - @Bean - SecurityWebFilterChain configure(ServerHttpSecurity http) { - http - .authorizeExchange((exchanges) -> - exchanges - .pathMatchers("/", "/public/**").permitAll() - .anyExchange().authenticated() - ) - .oauth2Login(withDefaults()) - .formLogin(withDefaults()) - .oauth2Client(withDefaults()); - return http.build(); - } - - @Bean - MapReactiveUserDetailsService userDetailsService() { - UserDetails userDetails = User.withDefaultPasswordEncoder() - .username("user") - .password("password") - .roles("USER") - .build(); - return new MapReactiveUserDetailsService(userDetails); - } -} diff --git a/samples/boot/oauth2webclient-webflux/src/main/java/sample/config/WebClientConfig.java b/samples/boot/oauth2webclient-webflux/src/main/java/sample/config/WebClientConfig.java deleted file mode 100644 index 6016aa2ef5..0000000000 --- a/samples/boot/oauth2webclient-webflux/src/main/java/sample/config/WebClientConfig.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.config; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager; -import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider; -import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder; -import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; -import org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager; -import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction; -import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; -import org.springframework.web.reactive.function.client.WebClient; - -/** - * @author Rob Winch - * @since 5.1 - */ -@Configuration -public class WebClientConfig { - - @Value("${resource-uri}") String uri; - - @Bean - WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) { - ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = - new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); - oauth.setDefaultOAuth2AuthorizedClient(true); - return WebClient.builder() - .baseUrl(this.uri) - .filter(oauth) - .build(); - } - - @Bean - ReactiveOAuth2AuthorizedClientManager authorizedClientManager( - ReactiveClientRegistrationRepository clientRegistrationRepository, - ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { - - ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = - ReactiveOAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken() - .clientCredentials() - .password() - .build(); - DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = - new DefaultReactiveOAuth2AuthorizedClientManager( - clientRegistrationRepository, authorizedClientRepository); - authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); - - return authorizedClientManager; - } -} diff --git a/samples/boot/oauth2webclient-webflux/src/main/java/sample/web/IndexController.java b/samples/boot/oauth2webclient-webflux/src/main/java/sample/web/IndexController.java deleted file mode 100644 index e1e0035ef1..0000000000 --- a/samples/boot/oauth2webclient-webflux/src/main/java/sample/web/IndexController.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.web; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; - -/** - * @author Rob Winch - */ -@Controller -public class IndexController { - @GetMapping("/") - String index() { - return "index"; - } -} diff --git a/samples/boot/oauth2webclient-webflux/src/main/java/sample/web/OAuth2WebClientController.java b/samples/boot/oauth2webclient-webflux/src/main/java/sample/web/OAuth2WebClientController.java deleted file mode 100644 index a1ddae90aa..0000000000 --- a/samples/boot/oauth2webclient-webflux/src/main/java/sample/web/OAuth2WebClientController.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.web; - -import reactor.core.publisher.Mono; - -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.reactive.function.client.WebClient; - -import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId; - -/** - * @author Joe Grandja - * @author Rob Winch - */ -@Controller -@RequestMapping(path = {"/webclient", "/public/webclient"}) -public class OAuth2WebClientController { - private final WebClient webClient; - - public OAuth2WebClientController(WebClient webClient) { - this.webClient = webClient; - } - - @GetMapping("/explicit") - String explicit(Model model) { - Mono body = this.webClient - .get() - .attributes(clientRegistrationId("client-id")) - .retrieve() - .bodyToMono(String.class); - model.addAttribute("body", body); - return "response"; - } - - @GetMapping("/implicit") - String implicit(Model model) { - Mono body = this.webClient - .get() - .retrieve() - .bodyToMono(String.class); - model.addAttribute("body", body); - return "response"; - } -} diff --git a/samples/boot/oauth2webclient-webflux/src/main/java/sample/web/RegisteredOAuth2AuthorizedClientController.java b/samples/boot/oauth2webclient-webflux/src/main/java/sample/web/RegisteredOAuth2AuthorizedClientController.java deleted file mode 100644 index 558277394f..0000000000 --- a/samples/boot/oauth2webclient-webflux/src/main/java/sample/web/RegisteredOAuth2AuthorizedClientController.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.web; - -import reactor.core.publisher.Mono; - -import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; -import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.reactive.function.client.WebClient; - -import static org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient; - -/** - * @author Joe Grandja - * @author Rob Winch - */ -@Controller -@RequestMapping(path = {"/annotation", "/public/annotation"}) -public class RegisteredOAuth2AuthorizedClientController { - - private final WebClient webClient; - - public RegisteredOAuth2AuthorizedClientController(WebClient webClient) { - this.webClient = webClient; - } - - @GetMapping("/explicit") - String explicit(Model model, @RegisteredOAuth2AuthorizedClient("client-id") OAuth2AuthorizedClient authorizedClient) { - Mono body = this.webClient - .get() - .attributes(oauth2AuthorizedClient(authorizedClient)) - .retrieve() - .bodyToMono(String.class); - model.addAttribute("body", body); - return "response"; - } - - @GetMapping("/implicit") - String implicit(Model model, @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient) { - Mono body = this.webClient - .get() - .attributes(oauth2AuthorizedClient(authorizedClient)) - .retrieve() - .bodyToMono(String.class); - model.addAttribute("body", body); - return "response"; - } -} diff --git a/samples/boot/oauth2webclient-webflux/src/main/resources/application.yml b/samples/boot/oauth2webclient-webflux/src/main/resources/application.yml deleted file mode 100644 index 8528a06d0d..0000000000 --- a/samples/boot/oauth2webclient-webflux/src/main/resources/application.yml +++ /dev/null @@ -1,21 +0,0 @@ -logging: - level: - root: INFO - org.springframework.web: INFO - org.springframework.security: INFO -# org.springframework.boot.autoconfigure: DEBUG - -spring: - thymeleaf: - cache: false - security: - oauth2: - client: - registration: - client-id: - client-id: replace-with-client-id - client-secret: replace-with-client-secret - provider: github - scope: read:user,public_repo - -resource-uri: https://api.github.com/user/repos diff --git a/samples/boot/oauth2webclient-webflux/src/main/resources/templates/index.html b/samples/boot/oauth2webclient-webflux/src/main/resources/templates/index.html deleted file mode 100644 index 7787a75dd7..0000000000 --- a/samples/boot/oauth2webclient-webflux/src/main/resources/templates/index.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - OAuth2 WebClient Showcase - - - -Log Out -

Examples

- -

@RegisteredOAuth2AuthorizedClient

-

-Examples on RegisteredOAuth2AuthorizedClientController -

Authenticated

-
    -
  • Explicit - Explicitly provide a Client Registration Id
  • -
  • - Implicit - Use the currently logged in user's OAuth Token. This will - only work if the user authenticates with oauth2Login and the token provided is the correct token provided at - log in is authorized.
  • -
-

Public

-
    -
  • Explicit - Explicitly provide a Client Registration Id
  • -
  • - Implicit - This will fail if the user is not authenticated. - Since it is mapped to permitAll, it is going to fail unless the user already took an action to log in and then - authenticates with oauth2Login()
  • -
- -

ServerOAuth2AuthorizedClientExchangeFilterFunction

-

- Examples on OAuth2WebClientController that demonstrate how to use ServerOAuth2AuthorizedClientExchangeFilterFunction -

Authenticated

-
    -
  • Explicit - Explicitly provide a Client Registration Id
  • -
  • - Implicit - Use the currently logged in user's OAuth Token. This will - only work if the user authenticates with oauth2Login and the token provided is the correct token provided at - log in is authorized.
  • -
-

Public

-
    -
  • Explicit - Explicitly provide a Client Registration Id
  • -
  • - Implicit - This will fail if the user is not authenticated. - Since it is mapped to permitAll, it is going to fail unless the user already took an action to log in and then - authenticates with oauth2Login()
  • -
- - diff --git a/samples/boot/oauth2webclient-webflux/src/main/resources/templates/response.html b/samples/boot/oauth2webclient-webflux/src/main/resources/templates/response.html deleted file mode 100644 index 210c18c29a..0000000000 --- a/samples/boot/oauth2webclient-webflux/src/main/resources/templates/response.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - OAuth2 WebClient Showcase - - - -Back -

Response

-
- - - diff --git a/samples/boot/oauth2webclient-webflux/src/test/java/sample/OAuth2WebClientControllerTests.java b/samples/boot/oauth2webclient-webflux/src/test/java/sample/OAuth2WebClientControllerTests.java deleted file mode 100644 index 52445dd212..0000000000 --- a/samples/boot/oauth2webclient-webflux/src/test/java/sample/OAuth2WebClientControllerTests.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.junit.AfterClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import sample.config.SecurityConfig; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; -import org.springframework.web.reactive.function.client.WebClient; - -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockOAuth2Client; -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockOAuth2Login; - -@WebFluxTest -@Import(SecurityConfig.class) -@AutoConfigureWebTestClient -@RunWith(SpringRunner.class) -public class OAuth2WebClientControllerTests { - private static MockWebServer web = new MockWebServer(); - - @Autowired - private WebTestClient client; - - @AfterClass - public static void shutdown() throws Exception { - web.shutdown(); - } - - @Test - public void explicitWhenAuthenticatedThenUsesClientIdRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.client.mutateWith(mockOAuth2Login()) - .mutateWith(mockOAuth2Client("client-id")) - .get().uri("/webclient/explicit") - .exchange() - .expectStatus().isOk(); - } - - @Test - public void implicitWhenAuthenticatedThenUsesDefaultRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.client.mutateWith(mockOAuth2Login()) - .get().uri("/webclient/implicit") - .exchange() - .expectStatus().isOk(); - } - - @Test - public void publicExplicitWhenAuthenticatedThenUsesClientIdRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.client.mutateWith(mockOAuth2Client("client-id")) - .get().uri("/public/webclient/explicit") - .exchange() - .expectStatus().isOk(); - } - - @Test - public void publicImplicitWhenAuthenticatedThenUsesDefaultRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.client.mutateWith(mockOAuth2Login()) - .get().uri("/public/webclient/implicit") - .exchange() - .expectStatus().isOk(); - } - - @TestConfiguration - static class WebClientConfig { - @Bean - WebClient web() { - return WebClient.create(web.url("/").toString()); - } - } -} diff --git a/samples/boot/oauth2webclient-webflux/src/test/java/sample/OAuth2WebClientWebFluxApplicationTests.java b/samples/boot/oauth2webclient-webflux/src/test/java/sample/OAuth2WebClientWebFluxApplicationTests.java deleted file mode 100644 index 657a6f7a16..0000000000 --- a/samples/boot/oauth2webclient-webflux/src/test/java/sample/OAuth2WebClientWebFluxApplicationTests.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; - -/** - * @author Rob Winch - */ -@SpringBootTest -@AutoConfigureWebTestClient -@RunWith(SpringRunner.class) -public class OAuth2WebClientWebFluxApplicationTests { - @Autowired - private WebTestClient client; - - @Test - public void annotationExplicitWhenNotAuthenticatedThenLoginRequested() { - this.client.get().uri("/annotation/explicit") - .exchange() - .expectStatus().is3xxRedirection(); - } -} diff --git a/samples/boot/oauth2webclient-webflux/src/test/java/sample/RegisteredOAuth2AuthorizedClientControllerTests.java b/samples/boot/oauth2webclient-webflux/src/test/java/sample/RegisteredOAuth2AuthorizedClientControllerTests.java deleted file mode 100644 index 32fc9095b7..0000000000 --- a/samples/boot/oauth2webclient-webflux/src/test/java/sample/RegisteredOAuth2AuthorizedClientControllerTests.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.junit.AfterClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import sample.config.SecurityConfig; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; -import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; -import org.springframework.web.reactive.function.client.WebClient; - -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockOAuth2Client; -import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.mockOAuth2Login; - -@WebFluxTest -@Import(SecurityConfig.class) -@AutoConfigureWebTestClient -@RunWith(SpringRunner.class) -public class RegisteredOAuth2AuthorizedClientControllerTests { - private static MockWebServer web = new MockWebServer(); - - @Autowired - private WebTestClient client; - - @AfterClass - public static void shutdown() throws Exception { - web.shutdown(); - } - - @Test - public void annotationExplicitWhenAuthenticatedThenUsesClientIdRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.client.mutateWith(mockOAuth2Login()) - .mutateWith(mockOAuth2Client("client-id")) - .get().uri("/annotation/explicit") - .exchange() - .expectStatus().isOk(); - } - - @Test - public void annotationImplicitWhenAuthenticatedThenUsesDefaultRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.client.mutateWith(mockOAuth2Login()) - .get().uri("/annotation/implicit") - .exchange() - .expectStatus().isOk(); - } - - @Test - public void publicAnnotationExplicitWhenAuthenticatedThenUsesClientIdRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.client.mutateWith(mockOAuth2Client("client-id")) - .get().uri("/public/annotation/explicit") - .exchange() - .expectStatus().isOk(); - } - - @Test - public void publicAnnotationImplicitWhenAuthenticatedThenUsesDefaultRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.client.mutateWith(mockOAuth2Login()) - .get().uri("/public/annotation/implicit") - .exchange() - .expectStatus().isOk(); - } - - @TestConfiguration - static class WebClientConfig { - @Bean - WebClient web() { - return WebClient.create(web.url("/").toString()); - } - } -} diff --git a/samples/boot/oauth2webclient/README.adoc b/samples/boot/oauth2webclient/README.adoc deleted file mode 100644 index b234f34f7e..0000000000 --- a/samples/boot/oauth2webclient/README.adoc +++ /dev/null @@ -1,63 +0,0 @@ -= OAuth 2.0 WebClient (Servlet) Sample - -== GitHub Repositories - -This guide provides instructions on setting up the sample application, which leverages WebClient OAuth2 integration to display a list of public GitHub repositories that are accessible to the authenticated user. - -This includes repositories owned by the authenticated user, repositories where the authenticated user is a collaborator, and repositories that the authenticated user has access to through an organization membership. - -The following sections provide detailed steps for setting up the sample and covers the following topics: - -* <> -* <> -* <> - -[[github-register-application]] -=== Register OAuth application - -To use GitHub's OAuth 2.0 authorization system, you must https://github.com/settings/applications/new[Register a new OAuth application]. - -When registering the OAuth application, ensure the *Authorization callback URL* is set to `http://localhost:8080/login/oauth2/code/client-id`. - -The Authorization callback URL (redirect URI) is the path in the application that the end-user's user-agent is redirected back to after they have authenticated with GitHub and have granted access to the OAuth application on the _Authorize application_ page. - -[[github-application-config]] -=== Configure application.yml - -Now that you have a new OAuth application with GitHub, you need to configure the sample to use the OAuth application for the _authorization code grant flow_. -To do so: - -. Go to `application.yml` and set the following configuration: -+ -[source,yaml] ----- -spring: - security: - oauth2: - client: - registration: <1> - client-id: <2> - client-id: replace-with-client-id - client-secret: replace-with-client-secret - provider: github - scope: read:user,public_repo ----- -+ -.OAuth Client properties -==== -<1> `spring.security.oauth2.client.registration` is the base property prefix for OAuth Client properties. -<2> Following the base property prefix is the ID for the `ClientRegistration`, which is github. -==== - -. Replace the values in the `client-id` and `client-secret` property with the OAuth 2.0 credentials you created earlier. - -[[github-boot-application]] -=== Boot up the application - -Launch the Spring Boot 2.0 sample and go to `http://localhost:8080`. -You are then redirected to the default _auto-generated_ form login page. -Log in using *'user'* (username) and *'password'* (password) or click the link to authenticate with GitHub and then you'll be redirected to GitHub for authentication. - -After authenticating with your GitHub credentials, the next page presented to you is "Authorize application". -This page will ask you to *Authorize* the application you created in the previous step. -Click _Authorize application_ to allow the OAuth application to access and display your public repository information. diff --git a/samples/boot/oauth2webclient/spring-security-samples-boot-oauth2webclient.gradle b/samples/boot/oauth2webclient/spring-security-samples-boot-oauth2webclient.gradle deleted file mode 100644 index f65d82709c..0000000000 --- a/samples/boot/oauth2webclient/spring-security-samples-boot-oauth2webclient.gradle +++ /dev/null @@ -1,16 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-oauth2-client') - compile project(':spring-security-oauth2-jose') - compile 'org.springframework:spring-webflux' - compile 'org.springframework.boot:spring-boot-starter-thymeleaf' - compile 'org.springframework.boot:spring-boot-starter-web' - compile 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' - compile 'io.projectreactor.netty:reactor-netty' - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' - testCompile 'com.squareup.okhttp3:mockwebserver' -} diff --git a/samples/boot/oauth2webclient/src/main/java/sample/OAuth2WebClientApplication.java b/samples/boot/oauth2webclient/src/main/java/sample/OAuth2WebClientApplication.java deleted file mode 100644 index 4c4a6b7de1..0000000000 --- a/samples/boot/oauth2webclient/src/main/java/sample/OAuth2WebClientApplication.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration; - -/** - * @author Joe Grandja - */ -// FIXME: Work around https://github.com/spring-projects/spring-boot/issues/14463 -@SpringBootApplication(exclude = ReactiveOAuth2ClientAutoConfiguration.class) -public class OAuth2WebClientApplication { - - public static void main(String[] args) { - SpringApplication.run(OAuth2WebClientApplication.class, args); - } -} diff --git a/samples/boot/oauth2webclient/src/main/java/sample/config/SecurityConfig.java b/samples/boot/oauth2webclient/src/main/java/sample/config/SecurityConfig.java deleted file mode 100644 index e5602d812d..0000000000 --- a/samples/boot/oauth2webclient/src/main/java/sample/config/SecurityConfig.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.config; - -import org.springframework.context.annotation.Bean; -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.WebSecurityConfigurerAdapter; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.provisioning.InMemoryUserDetailsManager; - -import static org.springframework.security.config.Customizer.withDefaults; - -/** - * @author Joe Grandja - */ -@EnableWebSecurity -public class SecurityConfig extends WebSecurityConfigurerAdapter { - - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .authorizeRequests((authorizeRequests) -> - authorizeRequests - .mvcMatchers("/", "/public/**").permitAll() - .anyRequest().authenticated() - ) - .formLogin(withDefaults()) - .oauth2Login(withDefaults()) - .oauth2Client(withDefaults()); - } - - @Bean - public UserDetailsService userDetailsService() { - UserDetails userDetails = User.withDefaultPasswordEncoder() - .username("user") - .password("password") - .roles("USER") - .build(); - return new InMemoryUserDetailsManager(userDetails); - } -} diff --git a/samples/boot/oauth2webclient/src/main/java/sample/config/WebClientConfig.java b/samples/boot/oauth2webclient/src/main/java/sample/config/WebClientConfig.java deleted file mode 100644 index da9510602b..0000000000 --- a/samples/boot/oauth2webclient/src/main/java/sample/config/WebClientConfig.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.config; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; -import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder; -import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; -import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager; -import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; -import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction; -import org.springframework.web.reactive.function.client.WebClient; - -/** - * @author Rob Winch - * @since 5.1 - */ -@Configuration -public class WebClientConfig { - - @Value("${resource-uri}") String resourceUri; - - @Bean - WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) { - ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 = - new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); - oauth2.setDefaultOAuth2AuthorizedClient(true); - return WebClient.builder() - .baseUrl(this.resourceUri) - .apply(oauth2.oauth2Configuration()) - .build(); - } - - @Bean - OAuth2AuthorizedClientManager authorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, - OAuth2AuthorizedClientRepository authorizedClientRepository) { - OAuth2AuthorizedClientProvider authorizedClientProvider = - OAuth2AuthorizedClientProviderBuilder.builder() - .authorizationCode() - .refreshToken() - .clientCredentials() - .password() - .build(); - DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( - clientRegistrationRepository, authorizedClientRepository); - authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); - - return authorizedClientManager; - } -} diff --git a/samples/boot/oauth2webclient/src/main/java/sample/web/IndexController.java b/samples/boot/oauth2webclient/src/main/java/sample/web/IndexController.java deleted file mode 100644 index e1e0035ef1..0000000000 --- a/samples/boot/oauth2webclient/src/main/java/sample/web/IndexController.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.web; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; - -/** - * @author Rob Winch - */ -@Controller -public class IndexController { - @GetMapping("/") - String index() { - return "index"; - } -} diff --git a/samples/boot/oauth2webclient/src/main/java/sample/web/OAuth2WebClientController.java b/samples/boot/oauth2webclient/src/main/java/sample/web/OAuth2WebClientController.java deleted file mode 100644 index f20b479d1f..0000000000 --- a/samples/boot/oauth2webclient/src/main/java/sample/web/OAuth2WebClientController.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.web; - -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.reactive.function.client.WebClient; - -import static org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId; - -/** - * @author Joe Grandja - * @author Rob Winch - */ -@Controller -@RequestMapping(path = {"/webclient", "/public/webclient"}) -public class OAuth2WebClientController { - private final WebClient webClient; - - public OAuth2WebClientController(WebClient webClient) { - this.webClient = webClient; - } - - @GetMapping("/explicit") - String explicit(Model model) { - String body = this.webClient - .get() - .attributes(clientRegistrationId("client-id")) - .retrieve() - .bodyToMono(String.class) - .block(); - model.addAttribute("body", body); - return "response"; - } - - @GetMapping("/implicit") - String implicit(Model model) { - String body = this.webClient - .get() - .retrieve() - .bodyToMono(String.class) - .block(); - model.addAttribute("body", body); - return "response"; - } -} diff --git a/samples/boot/oauth2webclient/src/main/java/sample/web/RegisteredOAuth2AuthorizedClientController.java b/samples/boot/oauth2webclient/src/main/java/sample/web/RegisteredOAuth2AuthorizedClientController.java deleted file mode 100644 index 883db445d0..0000000000 --- a/samples/boot/oauth2webclient/src/main/java/sample/web/RegisteredOAuth2AuthorizedClientController.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.web; - -import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; -import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.reactive.function.client.WebClient; - -import static org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient; - -/** - * @author Joe Grandja - * @author Rob Winch - */ -@Controller -@RequestMapping(path = {"/annotation", "/public/annotation"}) -public class RegisteredOAuth2AuthorizedClientController { - private final WebClient webClient; - - public RegisteredOAuth2AuthorizedClientController(WebClient webClient) { - this.webClient = webClient; - } - - @GetMapping("/explicit") - String explicit(Model model, @RegisteredOAuth2AuthorizedClient("client-id") OAuth2AuthorizedClient authorizedClient) { - String body = this.webClient - .get() - .attributes(oauth2AuthorizedClient(authorizedClient)) - .retrieve() - .bodyToMono(String.class) - .block(); - model.addAttribute("body", body); - return "response"; - } - - @GetMapping("/implicit") - String implicit(Model model, @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient) { - String body = this.webClient - .get() - .attributes(oauth2AuthorizedClient(authorizedClient)) - .retrieve() - .bodyToMono(String.class) - .block(); - model.addAttribute("body", body); - return "response"; - } -} diff --git a/samples/boot/oauth2webclient/src/main/resources/application.yml b/samples/boot/oauth2webclient/src/main/resources/application.yml deleted file mode 100644 index 8528a06d0d..0000000000 --- a/samples/boot/oauth2webclient/src/main/resources/application.yml +++ /dev/null @@ -1,21 +0,0 @@ -logging: - level: - root: INFO - org.springframework.web: INFO - org.springframework.security: INFO -# org.springframework.boot.autoconfigure: DEBUG - -spring: - thymeleaf: - cache: false - security: - oauth2: - client: - registration: - client-id: - client-id: replace-with-client-id - client-secret: replace-with-client-secret - provider: github - scope: read:user,public_repo - -resource-uri: https://api.github.com/user/repos diff --git a/samples/boot/oauth2webclient/src/main/resources/templates/index.html b/samples/boot/oauth2webclient/src/main/resources/templates/index.html deleted file mode 100644 index 07a8e68035..0000000000 --- a/samples/boot/oauth2webclient/src/main/resources/templates/index.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - OAuth2 WebClient Showcase - - - -Log Out -

Examples

- -

@RegisteredOAuth2AuthorizedClient

-

-Examples on RegisteredOAuth2AuthorizedClientController -

Authenticated

-
    -
  • Explicit - Explicitly provide a Client Registration Id
  • -
  • - Implicit - Use the currently logged in user's OAuth Token. This will - only work if the user authenticates with oauth2Login and the token provided is the correct token provided at - log in is authorized.
  • -
-

Public

-
    -
  • Explicit - Explicitly provide a Client Registration Id
  • -
  • - Implicit - This will fail if the user is not authenticated. - Since it is mapped to permitAll, it is going to fail unless the user already took an action to log in and then - authenticates with oauth2Login()
  • -
- -

ServletOAuth2AuthorizedClientExchangeFilterFunction

-

- Examples on OAuth2WebClientController that demonstrate how to use ServletOAuth2AuthorizedClientExchangeFilterFunction -

Authenticated

-
    -
  • Explicit - Explicitly provide a Client Registration Id
  • -
  • - Implicit - Use the currently logged in user's OAuth Token. This will - only work if the user authenticates with oauth2Login and the token provided is the correct token provided at - log in is authorized.
  • -
-

Public

-
    -
  • Explicit - Explicitly provide a Client Registration Id
  • -
  • - Implicit - This will fail if the user is not authenticated. - Since it is mapped to permitAll, it is going to fail unless the user already took an action to log in and then - authenticates with oauth2Login()
  • -
- - diff --git a/samples/boot/oauth2webclient/src/main/resources/templates/response.html b/samples/boot/oauth2webclient/src/main/resources/templates/response.html deleted file mode 100644 index 210c18c29a..0000000000 --- a/samples/boot/oauth2webclient/src/main/resources/templates/response.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - OAuth2 WebClient Showcase - - - -Back -

Response

-
- - - diff --git a/samples/boot/oauth2webclient/src/test/java/sample/OAuth2WebClientApplicationTests.java b/samples/boot/oauth2webclient/src/test/java/sample/OAuth2WebClientApplicationTests.java deleted file mode 100644 index 4e153b9961..0000000000 --- a/samples/boot/oauth2webclient/src/test/java/sample/OAuth2WebClientApplicationTests.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Test; -import org.junit.runner.RunWith; - -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.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -/** - * @author Rob Winch - */ -@SpringBootTest -@AutoConfigureMockMvc -@RunWith(SpringRunner.class) -public class OAuth2WebClientApplicationTests { - @Autowired - private MockMvc mockMvc; - - @Test - public void annotationExplicitWhenNotAuthenticatedThenLoginRequested() throws Exception { - this.mockMvc.perform(get("/annotation/explicit")) - .andExpect(status().is3xxRedirection()); - } -} diff --git a/samples/boot/oauth2webclient/src/test/java/sample/OAuth2WebClientControllerTests.java b/samples/boot/oauth2webclient/src/test/java/sample/OAuth2WebClientControllerTests.java deleted file mode 100644 index 8829c00471..0000000000 --- a/samples/boot/oauth2webclient/src/test/java/sample/OAuth2WebClientControllerTests.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.junit.AfterClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.web.reactive.function.client.WebClient; - -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.oauth2Client; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.oauth2Login; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@WebMvcTest -@AutoConfigureMockMvc -@RunWith(SpringRunner.class) -public class OAuth2WebClientControllerTests { - private static MockWebServer web = new MockWebServer(); - - @Autowired - private MockMvc mockMvc; - - @AfterClass - public static void shutdown() throws Exception { - web.shutdown(); - } - - @Test - public void explicitWhenAuthenticatedThenUsesClientIdRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.mockMvc.perform(get("/webclient/explicit") - .with(oauth2Login()) - .with(oauth2Client("client-id"))) - .andExpect(status().isOk()); - } - - @Test - public void implicitWhenAuthenticatedThenUsesDefaultRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.mockMvc.perform(get("/webclient/implicit") - .with(oauth2Login())) - .andExpect(status().isOk()); - } - - @Test - public void publicExplicitWhenAuthenticatedThenUsesClientIdRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.mockMvc.perform(get("/public/webclient/explicit") - .with(oauth2Client("client-id"))) - .andExpect(status().isOk()); - } - - @Test - public void publicImplicitWhenAuthenticatedThenUsesDefaultRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.mockMvc.perform(get("/public/webclient/implicit") - .with(oauth2Login())) - .andExpect(status().isOk()); - } - - @TestConfiguration - static class WebClientConfig { - @Bean - WebClient web() { - return WebClient.create(web.url("/").toString()); - } - } -} diff --git a/samples/boot/oauth2webclient/src/test/java/sample/RegisteredOAuth2AuthorizedClientControllerTests.java b/samples/boot/oauth2webclient/src/test/java/sample/RegisteredOAuth2AuthorizedClientControllerTests.java deleted file mode 100644 index 91e3a2ec91..0000000000 --- a/samples/boot/oauth2webclient/src/test/java/sample/RegisteredOAuth2AuthorizedClientControllerTests.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.junit.AfterClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.web.reactive.function.client.WebClient; - -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.oauth2Client; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.oauth2Login; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@WebMvcTest -@AutoConfigureMockMvc -@RunWith(SpringRunner.class) -public class RegisteredOAuth2AuthorizedClientControllerTests { - private static MockWebServer web = new MockWebServer(); - - @Autowired - private MockMvc mockMvc; - - @AfterClass - public static void shutdown() throws Exception { - web.shutdown(); - } - - @Test - public void annotationExplicitWhenAuthenticatedThenUsesClientIdRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.mockMvc.perform(get("/annotation/explicit") - .with(oauth2Login()) - .with(oauth2Client("client-id"))) - .andExpect(status().isOk()); - } - - @Test - public void annotationImplicitWhenAuthenticatedThenUsesDefaultRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.mockMvc.perform(get("/annotation/implicit") - .with(oauth2Login())) - .andExpect(status().isOk()); - } - - @Test - public void publicAnnotationExplicitWhenAuthenticatedThenUsesClientIdRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.mockMvc.perform(get("/public/annotation/explicit") - .with(oauth2Client("client-id"))) - .andExpect(status().isOk()); - } - - @Test - public void publicAnnotationImplicitWhenAuthenticatedThenUsesDefaultRegistration() throws Exception { - web.enqueue(new MockResponse().setBody("body").setResponseCode(200)); - this.mockMvc.perform(get("/public/annotation/implicit") - .with(oauth2Login())) - .andExpect(status().isOk()); - } - - @TestConfiguration - static class WebClientConfig { - @Bean - WebClient web() { - return WebClient.create(web.url("/").toString()); - } - } -} diff --git a/samples/boot/saml2login/README.adoc b/samples/boot/saml2login/README.adoc deleted file mode 100644 index d51b1bba4b..0000000000 --- a/samples/boot/saml2login/README.adoc +++ /dev/null @@ -1,38 +0,0 @@ -= SAML 2.0 Login Sample - -This guide provides instructions on setting up this SAML 2.0 Login sample application. - -The sample application uses Spring Boot and the `spring-security-saml2-service-provider` -module which is new in Spring Security 5.2. - -== Goals - -`saml2Login()` provides a very simple implementation of a Service Provider that can receive a SAML 2.0 Response via the HTTP-POST and HTTP-REDIRECT bindings against the SimpleSAMLphp SAML 2.0 reference implementation. - -The following features are implemented in the MVP: - -1. Receive and validate a SAML 2.0 Response containing an assertion, and create a corresponding authentication in Spring Security -2. Send a SAML 2.0 AuthNRequest to an Identity Provider -3. Provide a framework for components used in SAML 2.0 authentication that can be swapped by configuration -4. Work against the SimpleSAMLphp reference implementation - -== Run the Sample - -=== Start up the Sample Boot Application -``` - ./gradlew :spring-security-samples-boot-saml2login:bootRun -``` - -=== Open a Browser - -http://localhost:8080/ - -You will be redirect to the SimpleSAMLphp IDP - -=== Type in your credentials - -``` -User: user -Password: password -``` - diff --git a/samples/boot/saml2login/spring-security-samples-boot-saml2login.gradle b/samples/boot/saml2login/spring-security-samples-boot-saml2login.gradle deleted file mode 100644 index ee78e3f199..0000000000 --- a/samples/boot/saml2login/spring-security-samples-boot-saml2login.gradle +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -apply plugin: 'io.spring.convention.spring-sample-boot' - -sourceCompatibility = '11' - -repositories { - maven { url "https://build.shibboleth.net/nexus/content/repositories/releases/" } -} - -dependencies { - compile project(':spring-security-config') - compile project(':saml2-service-provider-opensaml4') - compile 'org.springframework.boot:spring-boot-starter-thymeleaf' - compile 'org.springframework.boot:spring-boot-starter-web' - compile 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' - - testCompile project(':spring-security-test') - testCompile 'net.sourceforge.htmlunit:htmlunit' - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/saml2login/src/integration-test/java/sample/Saml2LoginApplicationITests.java b/samples/boot/saml2login/src/integration-test/java/sample/Saml2LoginApplicationITests.java deleted file mode 100644 index c963ab3b2b..0000000000 --- a/samples/boot/saml2login/src/integration-test/java/sample/Saml2LoginApplicationITests.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import javax.servlet.http.HttpSession; - -import com.gargoylesoftware.htmlunit.WebClient; -import com.gargoylesoftware.htmlunit.html.HtmlForm; -import com.gargoylesoftware.htmlunit.html.HtmlInput; -import com.gargoylesoftware.htmlunit.html.HtmlPage; -import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput; -import org.junit.Test; -import org.junit.runner.RunWith; - -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.mock.web.MockHttpSession; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureMockMvc -public class Saml2LoginApplicationITests { - static final String SIGNED_RESPONSE = "PHNhbWxwOlJlc3BvbnNlIHhtbG5zOnNhbWxwPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6cHJvdG9jb2wiIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIElEPSJfY2UyYjU4NTVjZjU5YmEyNDc4OTUyOGRkOGQzZDcyOGRiMGViZjNlNzNiIiBWZXJzaW9uPSIyLjAiIElzc3VlSW5zdGFudD0iMjAyMS0wMS0yMFQwMTowMzoyNFoiIERlc3RpbmF0aW9uPSJodHRwOi8vbG9jYWxob3N0OjgwODAvbG9naW4vc2FtbDIvc3NvL29uZSIgSW5SZXNwb25zZVRvPSJBUlFjOThmMjAwLWRjZjctNGRmNC1hNTIyLTA3MjA2MjA4YjA3ZCI+PHNhbWw6SXNzdWVyPmh0dHBzOi8vc2ltcGxlc2FtbC1mb3Itc3ByaW5nLXNhbWwuYXBwcy5wY2ZvbmUuaW8vc2FtbDIvaWRwL21ldGFkYXRhLnBocDwvc2FtbDpJc3N1ZXI+PGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+CiAgPGRzOlNpZ25lZEluZm8+PGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz4KICAgIDxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNyc2Etc2hhMjU2Ii8+CiAgPGRzOlJlZmVyZW5jZSBVUkk9IiNfY2UyYjU4NTVjZjU5YmEyNDc4OTUyOGRkOGQzZDcyOGRiMGViZjNlNzNiIj48ZHM6VHJhbnNmb3Jtcz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz48ZHM6RGlnZXN0VmFsdWU+TXJUNS8wdTRScTl3QmMvejFQd2FrNURXZm1xOGlOVk52NldHZWFnZUVzUT08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU+WWg1UFE5cFVBbkkvOW5tNzgxZ040bThTS0U4T1VRTDVOMlI3ZklPZmtHVmMzRjhzNlJlR3hRNWFneUFXYnQzUDRwQ3RWeGtqbk4rMk5KeUw4QmhRMHN0dEovb2JFTHJGUldLemYyYUJaS2NCN0JHTFNtRXdoUFE3N3BHL0psMjBhaDQyaGRyWFc3TE9Ob0VZOHMyY093dm16NkQ2bW9YQWprMHV2UEVTNjhUVndxU2VmT3JwNXV0QmRSQUt6cUJRQ2NQWFJCdnB5NWJ3QkpDL2RKNE5QLzJpalE3N2I3eWhvVDQ0R21hSUduSGo0YVFaeG9kY1JuNU9oQ2hYRk4ydUk2YW1mT0ZYOThjUXZ5KzhDWm9YYUZRMnJmT2dPbGdzbmNGWGMwaXhYK05MSjlvSlJWT2hxRVpjY2JoZ3hPM2hpQ2UwemRuZHloVWxpaGMwdFU2OVlBPT08L2RzOlNpZ25hdHVyZVZhbHVlPgo8ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE+PGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlFRXpDQ0F2dWdBd0lCQWdJSkFJYzFxekxydis1bk1BMEdDU3FHU0liM0RRRUJDd1VBTUlHZk1Rc3dDUVlEVlFRR0V3SlZVekVMTUFrR0ExVUVDQXdDUTA4eEZEQVNCZ05WQkFjTUMwTmhjM1JzWlNCU2IyTnJNUnd3R2dZRFZRUUtEQk5UWVcxc0lGUmxjM1JwYm1jZ1UyVnlkbVZ5TVFzd0NRWURWUVFMREFKSlZERWdNQjRHQTFVRUF3d1hjMmx0Y0d4bGMyRnRiSEJvY0M1alptRndjSE11YVc4eElEQWVCZ2txaGtpRzl3MEJDUUVXRVdab1lXNXBhMEJ3YVhadmRHRnNMbWx2TUI0WERURTFNREl5TXpJeU5EVXdNMW9YRFRJMU1ESXlNakl5TkRVd00xb3dnWjh4Q3pBSkJnTlZCQVlUQWxWVE1Rc3dDUVlEVlFRSURBSkRUekVVTUJJR0ExVUVCd3dMUTJGemRHeGxJRkp2WTJzeEhEQWFCZ05WQkFvTUUxTmhiV3dnVkdWemRHbHVaeUJUWlhKMlpYSXhDekFKQmdOVkJBc01Ba2xVTVNBd0hnWURWUVFEREJkemFXMXdiR1Z6WVcxc2NHaHdMbU5tWVhCd2N5NXBiekVnTUI0R0NTcUdTSWIzRFFFSkFSWVJabWhoYm1sclFIQnBkbTkwWVd3dWFXOHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDNGNuNjJFMXhMcXBOMzRQbWJyS0Jia09YRmp6V2dKOWIrcFh1YVJmdDZBMzM5dXVJUWVvZUg1cWVTS1JWVGwzMkwwZ2R6Mlppdkx3WlhXK2NxdmZ0VlcxdHZFSHZ6SkZ5eGVUVzNmQ1VlQ1FzZWJMbkEycVJhMDdSa3hUbzZOZjI0NG1XV1JEb2Rjb0hFZkRVU2J4ZlRaNklFeFNvalNJVTJSbkQ2V2xsWVdGZEQxR0ZwQkpPbVFCOHJBYzh3SklCZEhGZFFuWDhUdGw3aFo2cnRncUVZTXpZVk11SjJGMnIxSFNVMXpTQXZ3cGRZUDZyUkdGUkpFZmRBOW1tM1dLZk5MU2M1Y2xqejBYL1RYeTB2VmxBVjk1bDlxY2ZGelBtcmtOSXN0OUZaU3dwdkI0OUx5QVZrZTA0RlFQUHdMZ1ZINGdwaGlKSDNqdlo3SStKNWxTOFZBZ01CQUFHalVEQk9NQjBHQTFVZERnUVdCQlRUeVA2Q2M1SGxCSjUrdWNWQ3dHYzVvZ0tOR3pBZkJnTlZIU01FR0RBV2dCVFR5UDZDYzVIbEJKNSt1Y1ZDd0djNW9nS05HekFNQmdOVkhSTUVCVEFEQVFIL01BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQXZNUzRFUWVQL2lwVjRqT0c1bE82L3RZQ2IvaUplQWR1T25SaGtKazBEYlgzMjlsRExaaFRUTC94L3cvOW11Q1ZjdkxyekVwNlBOK1ZXZnc1RTVGV3RaTjB5aEd0UDlSK3ZabnJWK29jMnpHRCtubzEveVNGT2UzRWlKQ081ZGVoeEtqWUVtQlJ2NXNVL0xaRktacG96S04vQk1FYTZDcUx1eGJ6Yjd5a3hWcjdFVkZYd2x0UHh6RTlUbUw5T0FDTk55RjVlSkhXTVJNbGxhclV2a2NYbGg0cHV4NGtzOWU2elY5RFFCeTJ6ZHM5ZjFJM3F4ZzBlWDZKbkdyWGkvWmlDVCtsSmdWZTNaRlhpZWppTEFpS0IwNHNYVzN0aTBMVzNseDEzWTFZbFE0L3RscGdUZ2ZJSnhLVjZueVBpTG9LMG55d2JNZCt2cEFpckR0Mk9jK2hrPC9kczpYNTA5Q2VydGlmaWNhdGU+PC9kczpYNTA5RGF0YT48L2RzOktleUluZm8+PC9kczpTaWduYXR1cmU+PHNhbWxwOlN0YXR1cz48c2FtbHA6U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIi8+PC9zYW1scDpTdGF0dXM+PHNhbWw6QXNzZXJ0aW9uIHhtbG5zOnhzaT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEtaW5zdGFuY2UiIHhtbG5zOnhzPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYSIgSUQ9Il9jYjYzYmMzNmMyYzAzYjRlMWJjZDViMWIwY2MyZTE2NWQwNDQ1NDZlODgiIFZlcnNpb249IjIuMCIgSXNzdWVJbnN0YW50PSIyMDIxLTAxLTIwVDAxOjAzOjI0WiI+PHNhbWw6SXNzdWVyPmh0dHBzOi8vc2ltcGxlc2FtbC1mb3Itc3ByaW5nLXNhbWwuYXBwcy5wY2ZvbmUuaW8vc2FtbDIvaWRwL21ldGFkYXRhLnBocDwvc2FtbDpJc3N1ZXI+PGRzOlNpZ25hdHVyZSB4bWxuczpkcz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyI+CiAgPGRzOlNpZ25lZEluZm8+PGRzOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz4KICAgIDxkczpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNyc2Etc2hhMjU2Ii8+CiAgPGRzOlJlZmVyZW5jZSBVUkk9IiNfY2I2M2JjMzZjMmMwM2I0ZTFiY2Q1YjFiMGNjMmUxNjVkMDQ0NTQ2ZTg4Ij48ZHM6VHJhbnNmb3Jtcz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnI2VudmVsb3BlZC1zaWduYXR1cmUiLz48ZHM6VHJhbnNmb3JtIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8+PC9kczpUcmFuc2Zvcm1zPjxkczpEaWdlc3RNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGVuYyNzaGEyNTYiLz48ZHM6RGlnZXN0VmFsdWU+VWFtN2NHVGlCd2xuRDBJdGd5aU5KVjN2Z0NPNytZZkRxSWJrWERkR3hrQT08L2RzOkRpZ2VzdFZhbHVlPjwvZHM6UmVmZXJlbmNlPjwvZHM6U2lnbmVkSW5mbz48ZHM6U2lnbmF0dXJlVmFsdWU+RkhpWUpETDlKTXM1Y2V5WXhUVVgrUndEQm45RFYzVE81dDFham4raGFtb1c2MUpBY0JaNjEwUHpYMzN3alA3Mk1kYmdDWnR5ZmNrSktZUUpPT0szRkxLTkJLQkphOTNsSS9rZWZjTXRTUGxBU2hESm9ydmU0U0tWa29WbzZLVnB0eC9OTnowRkhJNURFZTZiUUVjZWFiNERVNDFVdEpQMHUyWm16ejVjNC83VzhLdmt6MkxMbXhWZlE3Q2todmgvNzBhWHlkWVBVRml3bE4vV1lTV3JYVU9oOXNFTDFiZGVlQzFkYnpaeVdNNldnSkdRMUpJblBnSGd0YTlxMU96eGliOFlLRXpQSUMzVEZldkU1Y0phMFQvd1NzOVIxN0JSR09OclhTTWQvRCt4YkY0Z3lIYW5EZFlOYVN2TzdIS2p4bzRwYk1aY05peDhMTkVYZGtiZEx3PT08L2RzOlNpZ25hdHVyZVZhbHVlPgo8ZHM6S2V5SW5mbz48ZHM6WDUwOURhdGE+PGRzOlg1MDlDZXJ0aWZpY2F0ZT5NSUlFRXpDQ0F2dWdBd0lCQWdJSkFJYzFxekxydis1bk1BMEdDU3FHU0liM0RRRUJDd1VBTUlHZk1Rc3dDUVlEVlFRR0V3SlZVekVMTUFrR0ExVUVDQXdDUTA4eEZEQVNCZ05WQkFjTUMwTmhjM1JzWlNCU2IyTnJNUnd3R2dZRFZRUUtEQk5UWVcxc0lGUmxjM1JwYm1jZ1UyVnlkbVZ5TVFzd0NRWURWUVFMREFKSlZERWdNQjRHQTFVRUF3d1hjMmx0Y0d4bGMyRnRiSEJvY0M1alptRndjSE11YVc4eElEQWVCZ2txaGtpRzl3MEJDUUVXRVdab1lXNXBhMEJ3YVhadmRHRnNMbWx2TUI0WERURTFNREl5TXpJeU5EVXdNMW9YRFRJMU1ESXlNakl5TkRVd00xb3dnWjh4Q3pBSkJnTlZCQVlUQWxWVE1Rc3dDUVlEVlFRSURBSkRUekVVTUJJR0ExVUVCd3dMUTJGemRHeGxJRkp2WTJzeEhEQWFCZ05WQkFvTUUxTmhiV3dnVkdWemRHbHVaeUJUWlhKMlpYSXhDekFKQmdOVkJBc01Ba2xVTVNBd0hnWURWUVFEREJkemFXMXdiR1Z6WVcxc2NHaHdMbU5tWVhCd2N5NXBiekVnTUI0R0NTcUdTSWIzRFFFSkFSWVJabWhoYm1sclFIQnBkbTkwWVd3dWFXOHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDNGNuNjJFMXhMcXBOMzRQbWJyS0Jia09YRmp6V2dKOWIrcFh1YVJmdDZBMzM5dXVJUWVvZUg1cWVTS1JWVGwzMkwwZ2R6Mlppdkx3WlhXK2NxdmZ0VlcxdHZFSHZ6SkZ5eGVUVzNmQ1VlQ1FzZWJMbkEycVJhMDdSa3hUbzZOZjI0NG1XV1JEb2Rjb0hFZkRVU2J4ZlRaNklFeFNvalNJVTJSbkQ2V2xsWVdGZEQxR0ZwQkpPbVFCOHJBYzh3SklCZEhGZFFuWDhUdGw3aFo2cnRncUVZTXpZVk11SjJGMnIxSFNVMXpTQXZ3cGRZUDZyUkdGUkpFZmRBOW1tM1dLZk5MU2M1Y2xqejBYL1RYeTB2VmxBVjk1bDlxY2ZGelBtcmtOSXN0OUZaU3dwdkI0OUx5QVZrZTA0RlFQUHdMZ1ZINGdwaGlKSDNqdlo3SStKNWxTOFZBZ01CQUFHalVEQk9NQjBHQTFVZERnUVdCQlRUeVA2Q2M1SGxCSjUrdWNWQ3dHYzVvZ0tOR3pBZkJnTlZIU01FR0RBV2dCVFR5UDZDYzVIbEJKNSt1Y1ZDd0djNW9nS05HekFNQmdOVkhSTUVCVEFEQVFIL01BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQXZNUzRFUWVQL2lwVjRqT0c1bE82L3RZQ2IvaUplQWR1T25SaGtKazBEYlgzMjlsRExaaFRUTC94L3cvOW11Q1ZjdkxyekVwNlBOK1ZXZnc1RTVGV3RaTjB5aEd0UDlSK3ZabnJWK29jMnpHRCtubzEveVNGT2UzRWlKQ081ZGVoeEtqWUVtQlJ2NXNVL0xaRktacG96S04vQk1FYTZDcUx1eGJ6Yjd5a3hWcjdFVkZYd2x0UHh6RTlUbUw5T0FDTk55RjVlSkhXTVJNbGxhclV2a2NYbGg0cHV4NGtzOWU2elY5RFFCeTJ6ZHM5ZjFJM3F4ZzBlWDZKbkdyWGkvWmlDVCtsSmdWZTNaRlhpZWppTEFpS0IwNHNYVzN0aTBMVzNseDEzWTFZbFE0L3RscGdUZ2ZJSnhLVjZueVBpTG9LMG55d2JNZCt2cEFpckR0Mk9jK2hrPC9kczpYNTA5Q2VydGlmaWNhdGU+PC9kczpYNTA5RGF0YT48L2RzOktleUluZm8+PC9kczpTaWduYXR1cmU+PHNhbWw6U3ViamVjdD48c2FtbDpOYW1lSUQgU1BOYW1lUXVhbGlmaWVyPSJodHRwOi8vbG9jYWxob3N0OjgwODAvc2FtbDIvc2VydmljZS1wcm92aWRlci1tZXRhZGF0YS9vbmUiIEZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6MS4xOm5hbWVpZC1mb3JtYXQ6ZW1haWxBZGRyZXNzIj50ZXN0dXNlckBzcHJpbmcuc2VjdXJpdHkuc2FtbDwvc2FtbDpOYW1lSUQ+PHNhbWw6U3ViamVjdENvbmZpcm1hdGlvbiBNZXRob2Q9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpjbTpiZWFyZXIiPjxzYW1sOlN1YmplY3RDb25maXJtYXRpb25EYXRhIE5vdE9uT3JBZnRlcj0iMjA1Mi0wOS0yOFQwMjo1MDowNFoiIFJlY2lwaWVudD0iaHR0cDovL2xvY2FsaG9zdDo4MDgwL2xvZ2luL3NhbWwyL3Nzby9vbmUiIEluUmVzcG9uc2VUbz0iQVJRYzk4ZjIwMC1kY2Y3LTRkZjQtYTUyMi0wNzIwNjIwOGIwN2QiLz48L3NhbWw6U3ViamVjdENvbmZpcm1hdGlvbj48L3NhbWw6U3ViamVjdD48c2FtbDpDb25kaXRpb25zIE5vdEJlZm9yZT0iMjAyMS0wMS0yMFQwMTowMjo1NFoiIE5vdE9uT3JBZnRlcj0iMjA1Mi0wOS0yOFQwMjo1MDowNFoiPjxzYW1sOkF1ZGllbmNlUmVzdHJpY3Rpb24+PHNhbWw6QXVkaWVuY2U+aHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbWwyL3NlcnZpY2UtcHJvdmlkZXItbWV0YWRhdGEvb25lPC9zYW1sOkF1ZGllbmNlPjwvc2FtbDpBdWRpZW5jZVJlc3RyaWN0aW9uPjwvc2FtbDpDb25kaXRpb25zPjxzYW1sOkF1dGhuU3RhdGVtZW50IEF1dGhuSW5zdGFudD0iMjAyMS0wMS0yMFQwMDo0ODoyOVoiIFNlc3Npb25Ob3RPbk9yQWZ0ZXI9IjIwMjEtMDEtMjBUMDg6NDg6MjlaIiBTZXNzaW9uSW5kZXg9Il9lN2ExYTllNDk1YmZlMjI2NjQ5ZThkY2MzN2UxNDE1NDQ5NTIxNWQ2ZWIiPjxzYW1sOkF1dGhuQ29udGV4dD48c2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj51cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YWM6Y2xhc3NlczpQYXNzd29yZFByb3RlY3RlZFRyYW5zcG9ydDwvc2FtbDpBdXRobkNvbnRleHRDbGFzc1JlZj48L3NhbWw6QXV0aG5Db250ZXh0Pjwvc2FtbDpBdXRoblN0YXRlbWVudD48c2FtbDpBdHRyaWJ1dGVTdGF0ZW1lbnQ+PHNhbWw6QXR0cmlidXRlIE5hbWU9InVpZCIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDpiYXNpYyI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+dGVzdHVzZXJAc3ByaW5nLnNlY3VyaXR5LnNhbWw8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48c2FtbDpBdHRyaWJ1dGUgTmFtZT0iZWR1UGVyc29uQWZmaWxpYXRpb24iIE5hbWVGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphdHRybmFtZS1mb3JtYXQ6YmFzaWMiPjxzYW1sOkF0dHJpYnV0ZVZhbHVlIHhzaTp0eXBlPSJ4czpzdHJpbmciPm1lbWJlcjwvc2FtbDpBdHRyaWJ1dGVWYWx1ZT48c2FtbDpBdHRyaWJ1dGVWYWx1ZSB4c2k6dHlwZT0ieHM6c3RyaW5nIj51c2VyPC9zYW1sOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDpBdHRyaWJ1dGU+PHNhbWw6QXR0cmlidXRlIE5hbWU9ImVtYWlsQWRkcmVzcyIgTmFtZUZvcm1hdD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmF0dHJuYW1lLWZvcm1hdDpiYXNpYyI+PHNhbWw6QXR0cmlidXRlVmFsdWUgeHNpOnR5cGU9InhzOnN0cmluZyI+dGVzdHVzZXJAc3ByaW5nLnNlY3VyaXR5LnNhbWw8L3NhbWw6QXR0cmlidXRlVmFsdWU+PC9zYW1sOkF0dHJpYnV0ZT48L3NhbWw6QXR0cmlidXRlU3RhdGVtZW50Pjwvc2FtbDpBc3NlcnRpb24+PC9zYW1scDpSZXNwb25zZT4="; - - static final Map> USER_ATTRIBUTES = new LinkedHashMap<>(); - - static { - USER_ATTRIBUTES.put("uid", Arrays.asList("testuser@spring.security.saml")); - USER_ATTRIBUTES.put("eduPersonAffiliation", Arrays.asList("member", "user")); - USER_ATTRIBUTES.put("emailAddress", Arrays.asList("testuser@spring.security.saml")); - } - - @Autowired - MockMvc mvc; - - @Autowired - WebClient webClient; - - @Test - public void indexWhenSamlResponseThenShowsUserInformation() throws Exception { - HttpSession session = this.mvc.perform(get("http://localhost:8080/")) - .andExpect(status().is3xxRedirection()) - .andExpect(redirectedUrl("http://localhost:8080/saml2/authenticate/one")) - .andReturn() - .getRequest().getSession(); - - this.mvc.perform(post("http://localhost:8080/login/saml2/sso/one") - .param("SAMLResponse", SIGNED_RESPONSE) - .session((MockHttpSession) session)) - .andExpect(redirectedUrl("http://localhost:8080/")); - - this.mvc.perform(get("http://localhost:8080/") - .session((MockHttpSession) session)) - .andExpect(model().attribute("emailAddress", "testuser@spring.security.saml")) - .andExpect(model().attribute("userAttributes", USER_ATTRIBUTES)); - } - - @Test - public void authenticationAttemptWhenValidThenShowsUserEmailAddress() throws Exception { - HtmlPage assertingParty = this.webClient.getPage("/"); - HtmlForm form = assertingParty.getFormByName("f"); - HtmlInput username = form.getInputByName("username"); - HtmlInput password = form.getInputByName("password"); - HtmlSubmitInput submit = assertingParty.getHtmlElementById("submit_button"); - username.setValueAttribute("user"); - password.setValueAttribute("password"); - HtmlPage relyingParty = submit.click(); - assertThat(relyingParty.asText()) - .contains("You're email address is testuser@spring.security.saml"); - } -} diff --git a/samples/boot/saml2login/src/main/java/sample/IndexController.java b/samples/boot/saml2login/src/main/java/sample/IndexController.java deleted file mode 100644 index 8da3c251eb..0000000000 --- a/samples/boot/saml2login/src/main/java/sample/IndexController.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticatedPrincipal; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.GetMapping; - -@Controller -public class IndexController { - - @GetMapping("/") - public String index(Model model, - @AuthenticationPrincipal Saml2AuthenticatedPrincipal principal) { - String emailAddress = principal.getFirstAttribute("emailAddress"); - model.addAttribute("emailAddress", emailAddress); - model.addAttribute("userAttributes", principal.getAttributes()); - return "index"; - } -} diff --git a/samples/boot/saml2login/src/main/java/sample/Saml2LoginApplication.java b/samples/boot/saml2login/src/main/java/sample/Saml2LoginApplication.java deleted file mode 100644 index 08202d28de..0000000000 --- a/samples/boot/saml2login/src/main/java/sample/Saml2LoginApplication.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class Saml2LoginApplication { - - public static void main(String[] args) { - SpringApplication.run(Saml2LoginApplication.class, args); - } - -} diff --git a/samples/boot/saml2login/src/main/java/sample/SecurityConfig.java b/samples/boot/saml2login/src/main/java/sample/SecurityConfig.java deleted file mode 100644 index 434cf36668..0000000000 --- a/samples/boot/saml2login/src/main/java/sample/SecurityConfig.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2002-2020 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.saml2.provider.service.registration.InMemoryRelyingPartyRegistrationRepository; -import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistration; -import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; -import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrations; - -@Configuration -public class SecurityConfig { - @Bean - RelyingPartyRegistrationRepository relyingPartyRegistrationRepository() { - RelyingPartyRegistration relyingPartyRegistration = RelyingPartyRegistrations - .fromMetadataLocation("https://simplesaml-for-spring-saml.apps.pcfone.io/saml2/idp/metadata.php") - .registrationId("one") - .build(); - return new InMemoryRelyingPartyRegistrationRepository(relyingPartyRegistration); - } -} diff --git a/samples/boot/saml2login/src/main/resources/application.yml b/samples/boot/saml2login/src/main/resources/application.yml deleted file mode 100644 index 8b13789179..0000000000 --- a/samples/boot/saml2login/src/main/resources/application.yml +++ /dev/null @@ -1 +0,0 @@ - diff --git a/samples/boot/saml2login/src/main/resources/templates/index.html b/samples/boot/saml2login/src/main/resources/templates/index.html deleted file mode 100644 index b72bb58ce0..0000000000 --- a/samples/boot/saml2login/src/main/resources/templates/index.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - Spring Security - SAML 2.0 Login - - - - - -

SAML 2.0 Login with Spring Security

-

You are successfully logged in as

-

You're email address is

-

All Your Attributes

-
-
-
-
- - diff --git a/samples/boot/webflux-form/spring-security-samples-boot-webflux-form.gradle b/samples/boot/webflux-form/spring-security-samples-boot-webflux-form.gradle deleted file mode 100644 index 35d9a28149..0000000000 --- a/samples/boot/webflux-form/spring-security-samples-boot-webflux-form.gradle +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-core') - compile project(':spring-security-config') - compile project(':spring-security-web') - compile 'org.springframework.boot:spring-boot-starter-thymeleaf' - compile 'org.springframework.boot:spring-boot-starter-webflux' - compile 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' - - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' - testCompile 'io.projectreactor:reactor-test' - testCompile 'org.skyscreamer:jsonassert' - testCompile 'org.springframework:spring-test' - - integrationTestCompile seleniumDependencies -} - diff --git a/samples/boot/webflux-form/src/integration-test/java/sample/WebfluxFormApplicationTests.java b/samples/boot/webflux-form/src/integration-test/java/sample/WebfluxFormApplicationTests.java deleted file mode 100644 index c9062faa59..0000000000 --- a/samples/boot/webflux-form/src/integration-test/java/sample/WebfluxFormApplicationTests.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.htmlunit.HtmlUnitDriver; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.test.context.junit4.SpringRunner; - -import com.gargoylesoftware.htmlunit.BrowserVersion; - -import sample.webdriver.IndexPage; -import sample.webdriver.LoginPage; - -/** - * @author Rob Winch - * @since 5.0 - */ -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class WebfluxFormApplicationTests { - WebDriver driver; - - @LocalServerPort - int port; - - @Before - public void setup() { - this.driver = new HtmlUnitDriver(BrowserVersion.CHROME); - } - - @Test - public void loginWhenInvalidUsernameThenError() { - LoginPage login = IndexPage.to(this.driver, this.port, LoginPage.class); - login.assertAt(); - - login - .loginForm() - .username("invalid") - .password("password") - .submit(LoginPage.class) - .assertError(); - } - - @Test - public void loginAndLogout() { - LoginPage login = IndexPage.to(this.driver, this.port, LoginPage.class); - login.assertAt(); - - IndexPage index = login - .loginForm() - .username("user") - .password("password") - .submit(IndexPage.class); - index.assertAt(); - - login = index.logout(); - login - .assertAt() - .assertLogout(); - } -} diff --git a/samples/boot/webflux-form/src/integration-test/java/sample/webdriver/IndexPage.java b/samples/boot/webflux-form/src/integration-test/java/sample/webdriver/IndexPage.java deleted file mode 100644 index 9ca07b68f7..0000000000 --- a/samples/boot/webflux-form/src/integration-test/java/sample/webdriver/IndexPage.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.webdriver; - -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.PageFactory; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Rob Winch - * @since 5.0 - */ -public class IndexPage { - - private WebDriver driver; - - private WebElement logout; - - public IndexPage(WebDriver webDriver) { - this.driver = webDriver; - } - - public static T to(WebDriver driver, int port, Class page) { - driver.get("http://localhost:" + port +"/"); - return PageFactory.initElements(driver, page); - } - - public IndexPage assertAt() { - assertThat(this.driver.getTitle()).isEqualTo("Secured"); - return this; - } - - public LoginPage logout() { - this.logout.click(); - return LoginPage.create(this.driver); - } -} diff --git a/samples/boot/webflux-form/src/integration-test/java/sample/webdriver/LoginPage.java b/samples/boot/webflux-form/src/integration-test/java/sample/webdriver/LoginPage.java deleted file mode 100644 index 1058533866..0000000000 --- a/samples/boot/webflux-form/src/integration-test/java/sample/webdriver/LoginPage.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.webdriver; - -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.FindBy; -import org.openqa.selenium.support.PageFactory; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Rob Winch - * @since 5.0 - */ -public class LoginPage { - - private WebDriver driver; - @FindBy(css = "div[role=alert]") - private WebElement alert; - - private LoginForm loginForm; - - public LoginPage(WebDriver webDriver) { - this.driver = webDriver; - this.loginForm = PageFactory.initElements(webDriver, LoginForm.class); - } - - static LoginPage create(WebDriver driver) { - return PageFactory.initElements(driver, LoginPage.class); - } - - public LoginPage assertAt() { - assertThat(this.driver.getTitle()).isEqualTo("Please Log In"); - return this; - } - - public LoginPage assertError() { - assertThat(this.alert.getText()).isEqualTo("Invalid username and password."); - return this; - } - - public LoginPage assertLogout() { - assertThat(this.alert.getText()).isEqualTo("You have been logged out."); - return this; - } - - public LoginForm loginForm() { - return this.loginForm; - } - - public static class LoginForm { - private WebDriver driver; - private WebElement username; - private WebElement password; - @FindBy(css = "button[type=submit]") - private WebElement submit; - - public LoginForm(WebDriver driver) { - this.driver = driver; - } - - public LoginForm username(String username) { - this.username.sendKeys(username); - return this; - } - - public LoginForm password(String password) { - this.password.sendKeys(password); - return this; - } - - public T submit(Class page) { - this.submit.click(); - return PageFactory.initElements(this.driver, page); - } - } -} diff --git a/samples/boot/webflux-form/src/main/java/sample/IndexController.java b/samples/boot/webflux-form/src/main/java/sample/IndexController.java deleted file mode 100644 index d84301d78b..0000000000 --- a/samples/boot/webflux-form/src/main/java/sample/IndexController.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; - -/** - * @author Rob Winch - * @since 5.0 - */ -@Controller -public class IndexController { - - @GetMapping("/") - public String index() { - return "index"; - } - - @GetMapping("/login") - public String login() { - return "login"; - } -} diff --git a/samples/boot/webflux-form/src/main/java/sample/WebfluxFormApplication.java b/samples/boot/webflux-form/src/main/java/sample/WebfluxFormApplication.java deleted file mode 100644 index 48ddabcdb1..0000000000 --- a/samples/boot/webflux-form/src/main/java/sample/WebfluxFormApplication.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * @author Rob Winch - * @since 5.0 - */ -@SpringBootApplication -public class WebfluxFormApplication { - - public static void main(String[] args) { - SpringApplication.run(WebfluxFormApplication.class, args); - } -} diff --git a/samples/boot/webflux-form/src/main/java/sample/WebfluxFormSecurityConfig.java b/samples/boot/webflux-form/src/main/java/sample/WebfluxFormSecurityConfig.java deleted file mode 100644 index 94642742dc..0000000000 --- a/samples/boot/webflux-form/src/main/java/sample/WebfluxFormSecurityConfig.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.context.annotation.Bean; -import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; -import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.web.server.SecurityWebFilterChain; - -import static org.springframework.security.config.Customizer.withDefaults; - -/** - * @author Rob Winch - * @since 5.0 - */ -@EnableWebFluxSecurity -public class WebfluxFormSecurityConfig { - - @Bean - public MapReactiveUserDetailsService userDetailsService() { - UserDetails user = User.withDefaultPasswordEncoder() - .username("user") - .password("password") - .roles("USER") - .build(); - return new MapReactiveUserDetailsService(user); - } - - @Bean - SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { - http - .authorizeExchange((exchanges) -> - exchanges - .pathMatchers("/login").permitAll() - .anyExchange().authenticated() - ) - .httpBasic(withDefaults()) - .formLogin((formLogin) -> - formLogin - .loginPage("/login") - ); - return http.build(); - } -} diff --git a/samples/boot/webflux-form/src/main/resources/logback.xml b/samples/boot/webflux-form/src/main/resources/logback.xml deleted file mode 100644 index 3ebbcc0ddd..0000000000 --- a/samples/boot/webflux-form/src/main/resources/logback.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - diff --git a/samples/boot/webflux-form/src/main/resources/templates/index.html b/samples/boot/webflux-form/src/main/resources/templates/index.html deleted file mode 100644 index 992450d43f..0000000000 --- a/samples/boot/webflux-form/src/main/resources/templates/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - Secured - - - -
-

Secured

- -
- -
-
- - diff --git a/samples/boot/webflux-form/src/main/resources/templates/login.html b/samples/boot/webflux-form/src/main/resources/templates/login.html deleted file mode 100644 index 4fa5c65688..0000000000 --- a/samples/boot/webflux-form/src/main/resources/templates/login.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - Please Log In - - - - -
- -
- - diff --git a/samples/boot/webflux-x509/spring-security-samples-boot-webflux-x509.gradle b/samples/boot/webflux-x509/spring-security-samples-boot-webflux-x509.gradle deleted file mode 100644 index 57196d2b2b..0000000000 --- a/samples/boot/webflux-x509/spring-security-samples-boot-webflux-x509.gradle +++ /dev/null @@ -1,11 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-boot' - -dependencies { - compile project(':spring-security-core') - compile project(':spring-security-config') - compile project(':spring-security-web') - compile 'org.springframework.boot:spring-boot-starter-webflux' - - testCompile project(':spring-security-test') - testCompile 'org.springframework.boot:spring-boot-starter-test' -} diff --git a/samples/boot/webflux-x509/src/main/java/sample/MeController.java b/samples/boot/webflux-x509/src/main/java/sample/MeController.java deleted file mode 100644 index 7c10c6aedf..0000000000 --- a/samples/boot/webflux-x509/src/main/java/sample/MeController.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.security.core.context.ReactiveSecurityContextHolder; -import org.springframework.security.core.context.SecurityContext; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import reactor.core.publisher.Mono; - -/** - * @author Alexey Nesterov - * @since 5.2 - */ -@RestController -@RequestMapping("/me") -public class MeController { - - @GetMapping - public Mono me() { - return ReactiveSecurityContextHolder.getContext() - .map(SecurityContext::getAuthentication) - .map((authentication) -> "Hello, " + authentication.getName()); - } -} diff --git a/samples/boot/webflux-x509/src/main/java/sample/WebfluxX509Application.java b/samples/boot/webflux-x509/src/main/java/sample/WebfluxX509Application.java deleted file mode 100644 index 89813d073b..0000000000 --- a/samples/boot/webflux-x509/src/main/java/sample/WebfluxX509Application.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.context.annotation.Bean; -import org.springframework.security.config.web.server.ServerHttpSecurity; -import org.springframework.security.core.userdetails.MapReactiveUserDetailsService; -import org.springframework.security.core.userdetails.ReactiveUserDetailsService; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.web.server.SecurityWebFilterChain; - -import static org.springframework.security.config.Customizer.withDefaults; - -/** - * @author Alexey Nesterov - * @since 5.2 - */ -@SpringBootApplication -public class WebfluxX509Application { - - @Bean - public ReactiveUserDetailsService reactiveUserDetailsService() { - return new MapReactiveUserDetailsService( - User.withUsername("client").password("").authorities("ROLE_USER").build() - ); - } - - @Bean - public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { - // @formatter:off - http - .x509(withDefaults()) - .authorizeExchange((exchanges) -> - exchanges - .anyExchange().authenticated() - ); - // @formatter:on - - return http.build(); - } - - public static void main(String[] args) { - SpringApplication.run(WebfluxX509Application.class); - } -} diff --git a/samples/boot/webflux-x509/src/main/resources/application.yml b/samples/boot/webflux-x509/src/main/resources/application.yml deleted file mode 100644 index cdeb85fa7b..0000000000 --- a/samples/boot/webflux-x509/src/main/resources/application.yml +++ /dev/null @@ -1,8 +0,0 @@ -server: - port: 8443 - ssl: - key-store: 'classpath:./certs/server.p12' - key-store-password: 'password' - client-auth: need - trust-store: 'classpath:./certs/server.p12' - trust-store-password: 'password' diff --git a/samples/boot/webflux-x509/src/main/resources/certs/curl_app.sh b/samples/boot/webflux-x509/src/main/resources/certs/curl_app.sh deleted file mode 100644 index dbf7af4b43..0000000000 --- a/samples/boot/webflux-x509/src/main/resources/certs/curl_app.sh +++ /dev/null @@ -1,2 +0,0 @@ - curl -vvvv --cacert out/DevCA.crt --cert out/localhost.crt --key out/localhost.key https://localhost:8443/me - diff --git a/samples/boot/webflux-x509/src/main/resources/certs/server.p12 b/samples/boot/webflux-x509/src/main/resources/certs/server.p12 deleted file mode 100644 index ec536b2f60..0000000000 Binary files a/samples/boot/webflux-x509/src/main/resources/certs/server.p12 and /dev/null differ diff --git a/samples/boot/webflux-x509/src/test/java/sample/WebfluxX509ApplicationTest.java b/samples/boot/webflux-x509/src/test/java/sample/WebfluxX509ApplicationTest.java deleted file mode 100644 index e6ed9cf200..0000000000 --- a/samples/boot/webflux-x509/src/test/java/sample/WebfluxX509ApplicationTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample; - -import io.netty.handler.ssl.ClientAuth; -import io.netty.handler.ssl.SslContextBuilder; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.core.io.ClassPathResource; -import org.springframework.http.client.reactive.ClientHttpConnector; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.reactive.server.WebTestClient; -import reactor.netty.http.client.HttpClient; - -import java.io.IOException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.UnrecoverableEntryException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; - -import static org.assertj.core.api.Assertions.assertThat; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class WebfluxX509ApplicationTest { - - @LocalServerPort - int port; - - @Test - public void shouldExtractAuthenticationFromCertificate() throws Exception { - WebTestClient webTestClient = createWebTestClientWithClientCertificate(); - webTestClient - .get().uri("/me") - .exchange() - .expectStatus().isOk() - .expectBody() - .consumeWith((result) -> { - String responseBody = new String(result.getResponseBody()); - assertThat(responseBody).contains("Hello, client"); - }); - } - - private WebTestClient createWebTestClientWithClientCertificate() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableEntryException { - ClassPathResource serverKeystore = new ClassPathResource("/certs/server.p12"); - - KeyStore keyStore = KeyStore.getInstance("PKCS12"); - keyStore.load(serverKeystore.getInputStream(), "password".toCharArray()); - - X509Certificate devCA = (X509Certificate) keyStore.getCertificate("DevCA"); - - X509Certificate clientCrt = (X509Certificate) keyStore.getCertificate("client"); - KeyStore.Entry keyStoreEntry = keyStore.getEntry("client", - new KeyStore.PasswordProtection("password".toCharArray())); - PrivateKey clientKey = ((KeyStore.PrivateKeyEntry) keyStoreEntry).getPrivateKey(); - - SslContextBuilder sslContextBuilder = SslContextBuilder - .forClient().clientAuth(ClientAuth.REQUIRE) - .trustManager(devCA) - .keyManager(clientKey, clientCrt); - - HttpClient httpClient = HttpClient.create().secure((sslContextSpec) -> sslContextSpec.sslContext(sslContextBuilder)); - ClientHttpConnector httpConnector = new ReactorClientHttpConnector(httpClient); - - return WebTestClient - .bindToServer(httpConnector) - .baseUrl("https://localhost:" + port) - .build(); - } -} diff --git a/samples/certificates/Readme.txt b/samples/certificates/Readme.txt deleted file mode 100644 index 64b415cf83..0000000000 --- a/samples/certificates/Readme.txt +++ /dev/null @@ -1,10 +0,0 @@ -This directory contains certificates and keys for use with SSL in the sample applications. Certificates are issued by -our "Spring Security Test CA" certificate authority. - -ca.pem - the certificate authority's certificate. -server.jks - Java keystore containing the server certificate and privatekey. It Also contains the certificate authority - file and this is used as both keystore and truststore for they jetty server when running the samples with - the maven jetty plugin ("mvn jetty:run"). - -rod.p12, dianne.p12, scott.p12 are all certificate/key combinations for client authentication and can be installed in -your browser if you want to try out support for X.509 authentication. \ No newline at end of file diff --git a/samples/certificates/ca.pem b/samples/certificates/ca.pem deleted file mode 100644 index a5b52ca9d7..0000000000 --- a/samples/certificates/ca.pem +++ /dev/null @@ -1,22 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDojCCAoqgAwIBAgIEMKX1dzANBgkqhkiG9w0BAQUFADCBiTELMAkGA1UEBhMC -R0IxETAPBgNVBAgTCFNjb3RsYW5kMRAwDgYDVQQHEwdHbGFzZ293MRkwFwYDVQQK -ExBTcHJpbmcgRnJhbWV3b3JrMRgwFgYDVQQLEw9TcHJpbmcgU2VjdXJpdHkxIDAe -BgNVBAMTF1NwcmluZyBTZWN1cml0eSBUZXN0IENBMB4XDTA4MDEyNTExMTIyMVoX -DTE4MDIyNTAwMDAwMFowgYkxCzAJBgNVBAYTAkdCMREwDwYDVQQIEwhTY290bGFu -ZDEQMA4GA1UEBxMHR2xhc2dvdzEZMBcGA1UEChMQU3ByaW5nIEZyYW1ld29yazEY -MBYGA1UECxMPU3ByaW5nIFNlY3VyaXR5MSAwHgYDVQQDExdTcHJpbmcgU2VjdXJp -dHkgVGVzdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALzl/wEe -snYrwqaGZuB8hmwACtptazh1+eXCfd66FkioxlLF7yTnjCC7DT+vmMgSuThIEIsN -xlxLpEgyU3bU8GIuR8wyYIyvuSMcptdFJLV7NKYuRycxpDuqimTM7Br0nfNgKVEv -1QwguGWr6YN3aZ68/xe/D5xyPhakKu++7VFXIXw9f0+nqojdrFTqQ6l9GAVRgfX6 -h4JOaV1VFx83y2pnFj0iFneVxRcvXyWnyXlcOvJDIyVuyS/hYxb+E5rtBvp5XQ0o -5CP4OMwCZGx/jEqlL8oO7BwEgu9aEBxKvoIKJmHDTHgWIxgawTrKabmong4utnMI -yNrhsI77bmh2U7UCAwEAAaMQMA4wDAYDVR0PBAUDAwcGADANBgkqhkiG9w0BAQUF -AAOCAQEAuD8W9Ukkfyi0y65mwguFVAqBC3RSTMRXcjbLQV4rMDM/Q9kjA6acY4Ta -WgxGTwNCydqaqwDVsmn+6Je8Lp2xm9KLDLypVdNopGs+Mlfo55dhwqymXkQw1oJI -CPhR3nBmGEnSWW0UY9bPlpxRF2D5GDVwpuxDtXvWa4baPwRRI9MxwPWHA3ITl+fc -s9QVKy+pRAnuP9MSIp755cJ1CODOn2ElNCqnxxsZmcWcmI3LkHAwTmegl3PVvhrk -MKMEA/neshh/M/hWGNTFt77Hoa7pU9dv5RCWFvZPqsUgPrwGrmUvcmSDir3lSWQm -SuSED2LKVo+BFqwWS+jp49AR9b8B/Q== ------END CERTIFICATE----- diff --git a/samples/certificates/dianne.p12 b/samples/certificates/dianne.p12 deleted file mode 100755 index 6e5ba218db..0000000000 Binary files a/samples/certificates/dianne.p12 and /dev/null differ diff --git a/samples/certificates/localhost-with-ca/ca.crt b/samples/certificates/localhost-with-ca/ca.crt deleted file mode 100644 index 3371be5657..0000000000 --- a/samples/certificates/localhost-with-ca/ca.crt +++ /dev/null @@ -1,13 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIB9TCCAV4CCQCmYJRrKq63RDANBgkqhkiG9w0BAQUFADA+MQswCQYDVQQGEwJV -UzELMAkGA1UECAwCQ0ExEDAOBgNVBAoMB1Bpdm90YWwxEDAOBgNVBAMMB1Bpdm90 -YWwwIBcNMTMwODAxMTQzNTMyWhgPMjExMzA3MDgxNDM1MzJaMD4xCzAJBgNVBAYT -AlVTMQswCQYDVQQIDAJDQTEQMA4GA1UECgwHUGl2b3RhbDEQMA4GA1UEAwwHUGl2 -b3RhbDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArcTaLxERklIzLRqWwvZK -arXaePSnq+U0fLmhlw6i9cn67vUGbUzjOkeezPf/fWVHK23bdZxbxTQHJh4g5gw5 -o80RYs7tfGuYJNF2EomAGg83TaqjttF3HW1Ewf2rvAJdfyQyMUS8CxxJeRDMYb9+ -jYE0g5A4oRgzNgYSinjB2M8CAwEAATANBgkqhkiG9w0BAQUFAAOBgQAN60FcUgjK -/FXKCOxJ81Y2HG2TE9n237uGKtXs/D2VEv6rogEqRTWBs8VvErH5dgOwmUHWo7Ys -UloaPWrMfEQ/MuQDHknVItUK1fmHxAhje4WsmX2vSnGLLeoWiL92DnO/E10tbMoI -Is0A7KS2r3FAoIKrMYZNkGhMYpV2aEbSKg== ------END CERTIFICATE----- diff --git a/samples/certificates/localhost-with-ca/ca.csr b/samples/certificates/localhost-with-ca/ca.csr deleted file mode 100644 index 839d47c4c1..0000000000 --- a/samples/certificates/localhost-with-ca/ca.csr +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN CERTIFICATE REQUEST----- -MIIBfTCB5wIBADA+MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExEDAOBgNVBAoM -B1Bpdm90YWwxEDAOBgNVBAMMB1Bpdm90YWwwgZ8wDQYJKoZIhvcNAQEBBQADgY0A -MIGJAoGBAK3E2i8REZJSMy0alsL2Smq12nj0p6vlNHy5oZcOovXJ+u71Bm1M4zpH -nsz3/31lRytt23WcW8U0ByYeIOYMOaPNEWLO7XxrmCTRdhKJgBoPN02qo7bRdx1t -RMH9q7wCXX8kMjFEvAscSXkQzGG/fo2BNIOQOKEYMzYGEop4wdjPAgMBAAGgADAN -BgkqhkiG9w0BAQUFAAOBgQAONY6xNj0ODLnb4sWdARQqmHt1yic0GRbN3GXTBVuA -IJ+tUF9OykTSqf5IzWpJL/7ATQFnTMW3qJ8e0sSn61QU7yKHlBHHLCy92mTV5Lq/ -CIe1uoC5dHaNe7HMfFouHBjydAnn9vlkvvu781xhS8VXoRgYt3Vi5edQ6AIZFf58 -CA== ------END CERTIFICATE REQUEST----- diff --git a/samples/certificates/localhost-with-ca/ca.key b/samples/certificates/localhost-with-ca/ca.key deleted file mode 100644 index 547c189f33..0000000000 --- a/samples/certificates/localhost-with-ca/ca.key +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXgIBAAKBgQCtxNovERGSUjMtGpbC9kpqtdp49Ker5TR8uaGXDqL1yfru9QZt -TOM6R57M9/99ZUcrbdt1nFvFNAcmHiDmDDmjzRFizu18a5gk0XYSiYAaDzdNqqO2 -0XcdbUTB/au8Al1/JDIxRLwLHEl5EMxhv36NgTSDkDihGDM2BhKKeMHYzwIDAQAB -AoGBAITgykNBlyE/8FhmQ7EUazWMmGL0Gx+MZwWVYebET4MKj/OYtPBx4jSXvexZ -HCsEflbMbAxUo6x6K5lPYrLn2E6RxN3TFdlzG+lApuUi24oDON++p0Xa52aKQ6Ye -JSZLZZyDAUDN/byDgnf5BqnFwjJuv9tRdnguTB3W17uRqRrZAkEA3KarWpAKp0z5 -BiPZubNx9D94uwJVK4AaOIrdHZGpHe4qKkkIk7eZ95kopmavm5EsQBiRnTymWHJL -M+LU77i85QJBAMmbdN5mDd66HDdewjb3o125Kfcedu74gHoxOdeMnSZCop0GBtKQ -yeCi/pQzLm/wLaFwZ5NBurfipsY0YD71F6MCQQDEzO8mnjSyVWgCvvURuWhY9kej -XIhEfURlzA09s05IgMUg4/T/c5GjEfr8t7fHJCt4m7E8sfyYBJDonVdY3Me1AkEA -hptZ64e+KQCgCEQnbiXnmJMhttJLXIDk3zDwyr8iycHh6u90LLDpaSfKzE5j6e81 -uD1hmktfjJky+tFLlZ10+wJAVbart8oKuoNL7/J3TlDnk/ibOxiUrpGQ8GyEtUyY -/tnF0aeVhxfKaaOJy9E2wAaJ3ySqAvuuO5FYAo9sTu+KfQ== ------END RSA PRIVATE KEY----- diff --git a/samples/certificates/localhost-with-ca/ca.key.org b/samples/certificates/localhost-with-ca/ca.key.org deleted file mode 100644 index e04bb194f8..0000000000 --- a/samples/certificates/localhost-with-ca/ca.key.org +++ /dev/null @@ -1,18 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: DES-EDE3-CBC,102D7604E722947D - -lyUWkOAgjDtEJbc3/EvenlBpRN3T4N8lb2NNJu7cr6V03sgfayE/5yFk046GA4JV -J0JcbU913KN0iQy+oQMcqsMPRSUGmF4rNw2zCWGjVcfva/bHHr5HzKRZEGuwz4A1 -VD5tv0bZoL1XoZleFT3WQ0kquY/jHHSP/N5mzIBvv25E5ILo04hrVEqbOB4l2hby -MRPL4deWFZ2aW9RF4TuNVlI3FkWCseNAIj7Go5SfxyZ+s37DwHfHdil8U68AxSjf -1ccjAAzwLEv8I4UzXKn0P8OsnPb3WWuldEMAHFp6CshHRHHEPbe9bfseOE3ZHnq6 -YZ7qu8BWtHyKSYLtUh7axY6JRHc4fT5LXVly8aVLSFjqfjyM4de3qZ5SpTWnxPlR -8OZuu+pcqbNqTJtNB6R9j4GYWSxIi3blq3D1LVtxUh+wmxZxbK3UZOHAzWWFIojX -INHyfVXu70tIQKGoyCwLVWyArHIYzt7ZZF/Sa0lwbZRJnJGCGf1b2+bIX9AsUbWC -Zmi+Yu9hMtdzdhqsmRnnrEkH+yhsx+w6q4UuoPv0sPFTD3PXlk1cJtKGDbOjRzsQ -dAcShQFJK+z59LqPkhi76tBnQ8/LTJZHLdTZc/pL8myGT8rxYwkr05kM5fQu8+SJ -qIzcnm830fGr4eFJsJ24KKB38yUnNdtWOkeeSe80Tm1uLYd+ZbcWMVNdoESG4KQV -VURDP4zhZx2d0/4VCPr13USoQJ7En4qRvdb8vAsNpXZga9eDMcykeRDY6Szb3K5C -tQhX1pawMDNaHAMAAKGMvH9mm6D7gA4RlKc8LFgol6o22piuFhtHWA== ------END RSA PRIVATE KEY----- diff --git a/samples/certificates/localhost-with-ca/generate.sh b/samples/certificates/localhost-with-ca/generate.sh deleted file mode 100644 index 39506dab09..0000000000 --- a/samples/certificates/localhost-with-ca/generate.sh +++ /dev/null @@ -1,13 +0,0 @@ -openssl genrsa -des3 -passout pass:changeit -out ca.key 1024 -openssl req -new -passin pass:changeit -key ca.key -out ca.csr -cp ca.key ca.key.org -openssl rsa -in ca.key.org -passin pass:changeit -out ca.key -openssl x509 -req -days 36500 -passin pass:changeit -in ca.csr -signkey ca.key -out ca.crt - -keytool -genkey -storepass changeit -alias tomcat -keyalg RSA -keytool -storepass changeit -alias tomcat -certreq -file tomcat.csr -echo 02 > serial.txt -openssl x509 -CA ca.crt -passin pass:changeit -CAkey ca.key -CAserial serial.txt -req -in tomcat.csr -out tomcat.cer -days 36500 -rm serial.txt -keytool -storepass changeit -import -alias ca -file ca.crt -keytool -storepass changeit -import -alias tomcat -file tomcat.cer diff --git a/samples/certificates/localhost-with-ca/tomcat.cer b/samples/certificates/localhost-with-ca/tomcat.cer deleted file mode 100644 index f0569b6602..0000000000 --- a/samples/certificates/localhost-with-ca/tomcat.cer +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICkjCCAfsCAQMwDQYJKoZIhvcNAQEFBQAwPjELMAkGA1UEBhMCVVMxCzAJBgNV -BAgMAkNBMRAwDgYDVQQKDAdQaXZvdGFsMRAwDgYDVQQDDAdQaXZvdGFsMCAXDTEz -MDgwMTE0MzU1MVoYDzIxMTMwNzA4MTQzNTUxWjBfMQswCQYDVQQGEwJVUzELMAkG -A1UECBMCTU8xCzAJBgNVBAcTAktDMREwDwYDVQQKEwhTZWN1cml0eTEPMA0GA1UE -CxMGU3ByaW5nMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUA -A4IBDwAwggEKAoIBAQCKCyVI5D4h0lWU9D40P0kHkADWONRLQ9o0fcQvJmQaLwJN -tL0KpDiAwXiot4KKZWMGmYKoFtvhnd/t7ybZsODqsImDCZjKKvHaMTpFOyrl9SHW -PT7bvt7jBL47QqL/UJ0bApxVMmLD0DhcOmTkMmzm932F/he9w5z1nIsVl4POX+hQ -yyuuS+AvZdnUr5W2+COsvI1hsibrpnUnIvcXPHmSVrl4kD16OJ3Z/8Baia4mC3sy -pxqXCiBUeWbDsR5s9tZtMOJH7PpDbLsxGR3Zely4xWx7fmn/lW57EFyhMjXWZfUH -pTRsPWlFEYdTdnyM00MWWXrt+Y3kW9mb3w2DCf2fAgMBAAEwDQYJKoZIhvcNAQEF -BQADgYEAR1Y5IIfRrFIKTOc7gx4X2IOyByNdMYfd1+CWnEycUNuFwCE5iBJAbyN6 -yy2kViSFuTHwyJVD49QJNiFXOKZYmE8EFke1Y3nxwwe9MqfeTsrHpYGtpSZwDzv9 -64UM0qOPWxt+P9txQShcokldSt8BZ4iOJ9G6yY5EQdswE6rGkts= ------END CERTIFICATE----- diff --git a/samples/certificates/localhost-with-ca/tomcat.csr b/samples/certificates/localhost-with-ca/tomcat.csr deleted file mode 100644 index e6bbf82116..0000000000 --- a/samples/certificates/localhost-with-ca/tomcat.csr +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN NEW CERTIFICATE REQUEST----- -MIIC1DCCAbwCAQAwXzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1PMQswCQYDVQQHEwJLQzERMA8G -A1UEChMIU2VjdXJpdHkxDzANBgNVBAsTBlNwcmluZzESMBAGA1UEAxMJbG9jYWxob3N0MIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAigslSOQ+IdJVlPQ+ND9JB5AA1jjUS0PaNH3ELyZk -Gi8CTbS9CqQ4gMF4qLeCimVjBpmCqBbb4Z3f7e8m2bDg6rCJgwmYyirx2jE6RTsq5fUh1j0+277e -4wS+O0Ki/1CdGwKcVTJiw9A4XDpk5DJs5vd9hf4XvcOc9ZyLFZeDzl/oUMsrrkvgL2XZ1K+Vtvgj -rLyNYbIm66Z1JyL3Fzx5kla5eJA9ejid2f/AWomuJgt7MqcalwogVHlmw7EebPbWbTDiR+z6Q2y7 -MRkd2XpcuMVse35p/5VuexBcoTI11mX1B6U0bD1pRRGHU3Z8jNNDFll67fmN5FvZm98Ngwn9nwID -AQABoDAwLgYJKoZIhvcNAQkOMSEwHzAdBgNVHQ4EFgQUpQODsrGvfB6TWTCIEEdx0OKB1+QwDQYJ -KoZIhvcNAQELBQADggEBACL6M4Htn6tEebOH8vj3R8cVcgebxshQV/KD7+tWUq2RSno4JndsYxEF -H3Zh3vWhh5Q0nH55s1C/kiKYNP0jQXheeAiH6hatiCpSssgvDnw653ivBgqT3mo8sy1jpw9Pdx7F -6JuCksus+aI9PUKuI3DXXyAxKJfc/JmnnCXsyZz8sVu66bMrIel0kAODN6Da35QohDuStNuplu/R -ZHoiapQi3dxmWctC30fz0y7xqRVbRUKWHE7YWXqtWjFusUjXtZJobMeEb6DLeFfRsJ50OG8kgyZy -TvWQ9kP3ODeDqq74xiy7NxwGH8ytsWEwpSC10Z35vWb++rtl963A2itoK4E= ------END NEW CERTIFICATE REQUEST----- diff --git a/samples/certificates/rod.p12 b/samples/certificates/rod.p12 deleted file mode 100755 index 4cd0564430..0000000000 Binary files a/samples/certificates/rod.p12 and /dev/null differ diff --git a/samples/certificates/scott.p12 b/samples/certificates/scott.p12 deleted file mode 100644 index f0a6357e73..0000000000 Binary files a/samples/certificates/scott.p12 and /dev/null differ diff --git a/samples/certificates/server.jks b/samples/certificates/server.jks deleted file mode 100755 index aaa1119fff..0000000000 Binary files a/samples/certificates/server.jks and /dev/null differ diff --git a/samples/javaconfig/aspectj/spring-security-samples-javaconfig-aspectj.gradle b/samples/javaconfig/aspectj/spring-security-samples-javaconfig-aspectj.gradle deleted file mode 100644 index 6487a14d43..0000000000 --- a/samples/javaconfig/aspectj/spring-security-samples-javaconfig-aspectj.gradle +++ /dev/null @@ -1,20 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample' -apply plugin: 'io.freefair.aspectj.post-compile-weaving' - -repositories { - mavenCentral() -} - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-core') - - aspect project(':spring-security-aspects') - - runtime project(':spring-security-aspects') -} - -aspectj { - version = aspectjVersion -} - diff --git a/samples/javaconfig/aspectj/src/main/java/sample/aspectj/AspectjSecurityConfig.java b/samples/javaconfig/aspectj/src/main/java/sample/aspectj/AspectjSecurityConfig.java deleted file mode 100644 index 038b8271f3..0000000000 --- a/samples/javaconfig/aspectj/src/main/java/sample/aspectj/AspectjSecurityConfig.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.aspectj; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.AdviceMode; -import org.springframework.context.annotation.Bean; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; - -/** - * @author Rob Winch - */ -@EnableGlobalMethodSecurity(mode = AdviceMode.ASPECTJ, securedEnabled = true) -public class AspectjSecurityConfig { - @Bean - public Service service() { - return new Service(); - } - - @Bean - public SecuredService securedService() { - return new SecuredService(); - } - - @Autowired - public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication(); - } -} diff --git a/samples/javaconfig/aspectj/src/main/java/sample/aspectj/SecuredService.java b/samples/javaconfig/aspectj/src/main/java/sample/aspectj/SecuredService.java deleted file mode 100644 index 9f81cf1733..0000000000 --- a/samples/javaconfig/aspectj/src/main/java/sample/aspectj/SecuredService.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.aspectj; - -import org.springframework.security.access.annotation.Secured; - -/** - * Service which is secured on the class level - * - * @author Mike Wiesner - * @since 3.0 - */ -@Secured("ROLE_USER") -public class SecuredService { - - public void secureMethod() { - // nothing - } - -} diff --git a/samples/javaconfig/aspectj/src/main/java/sample/aspectj/Service.java b/samples/javaconfig/aspectj/src/main/java/sample/aspectj/Service.java deleted file mode 100644 index 70b8c0c71f..0000000000 --- a/samples/javaconfig/aspectj/src/main/java/sample/aspectj/Service.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.aspectj; - -import org.springframework.security.access.annotation.Secured; - -/** - * Service which is secured on method level - * - * @author Mike Wiesner - * @since 1.0 - */ -public class Service { - - @Secured("ROLE_USER") - public void secureMethod() { - // nothing - } - - public void publicMethod() { - // nothing - } - -} diff --git a/samples/javaconfig/aspectj/src/test/java/sample/aspectj/AspectJInterceptorTests.java b/samples/javaconfig/aspectj/src/test/java/sample/aspectj/AspectJInterceptorTests.java deleted file mode 100644 index 344de63e11..0000000000 --- a/samples/javaconfig/aspectj/src/test/java/sample/aspectj/AspectJInterceptorTests.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package sample.aspectj; - -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; - - -import org.springframework.security.core.Authentication; -import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import java.lang.reflect.Proxy; - -import static org.assertj.core.api.Assertions.assertThat; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = AspectjSecurityConfig.class) -public class AspectJInterceptorTests { - private Authentication admin = new UsernamePasswordAuthenticationToken("test", "xxx", - AuthorityUtils.createAuthorityList("ROLE_ADMIN")); - private Authentication user = new UsernamePasswordAuthenticationToken("test", "xxx", - AuthorityUtils.createAuthorityList("ROLE_USER")); - - @Autowired - private Service service; - - @Autowired - private SecuredService securedService; - - @Test - public void publicMethod() { - service.publicMethod(); - } - - @Test(expected = AuthenticationCredentialsNotFoundException.class) - public void securedMethodNotAuthenticated() { - service.secureMethod(); - } - - @Test(expected = AccessDeniedException.class) - public void securedMethodWrongRole() { - SecurityContextHolder.getContext().setAuthentication(admin); - service.secureMethod(); - } - - @Test - public void securedMethodEverythingOk() { - SecurityContextHolder.getContext().setAuthentication(user); - service.secureMethod(); - } - - @Test(expected = AuthenticationCredentialsNotFoundException.class) - public void securedClassNotAuthenticated() { - securedService.secureMethod(); - } - - @Test(expected = AccessDeniedException.class) - public void securedClassWrongRole() { - SecurityContextHolder.getContext().setAuthentication(admin); - securedService.secureMethod(); - } - - @Test(expected = AccessDeniedException.class) - public void securedClassWrongRoleOnNewedInstance() { - SecurityContextHolder.getContext().setAuthentication(admin); - new SecuredService().secureMethod(); - } - - @Test - public void securedClassEverythingOk() { - SecurityContextHolder.getContext().setAuthentication(user); - securedService.secureMethod(); - new SecuredService().secureMethod(); - } - - // SEC-2595 - @Test - public void notProxy() { - assertThat(Proxy.isProxyClass(securedService.getClass())).isFalse(); - } - - @After - public void tearDown() { - SecurityContextHolder.clearContext(); - } -} diff --git a/samples/javaconfig/aspectj/src/test/resources/logback-test.xml b/samples/javaconfig/aspectj/src/test/resources/logback-test.xml deleted file mode 100644 index 2d51ba4180..0000000000 --- a/samples/javaconfig/aspectj/src/test/resources/logback-test.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - - - diff --git a/samples/javaconfig/concurrency/spring-security-samples-javaconfig-concurrency.gradle b/samples/javaconfig/concurrency/spring-security-samples-javaconfig-concurrency.gradle deleted file mode 100644 index 7a8e417d8e..0000000000 --- a/samples/javaconfig/concurrency/spring-security-samples-javaconfig-concurrency.gradle +++ /dev/null @@ -1,20 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-war' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-core') - compile project(':spring-security-samples-javaconfig-messages') - compile project(':spring-security-web') - compile 'javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api' - compile 'javax.validation:validation-api' - compile 'org.hibernate:hibernate-validator' - compile 'org.springframework:spring-jdbc' - compile 'org.springframework:spring-webmvc' - compile slf4jDependencies - - providedCompile 'javax.servlet.jsp:javax.servlet.jsp-api' - providedCompile 'javax.servlet:javax.servlet-api:3.0.1' - - runtime 'ch.qos.logback:logback-classic' - runtime 'opensymphony:sitemesh' -} diff --git a/samples/javaconfig/concurrency/src/main/java/org/springframework/security/samples/config/MessageSecurityWebApplicationInitializer.java b/samples/javaconfig/concurrency/src/main/java/org/springframework/security/samples/config/MessageSecurityWebApplicationInitializer.java deleted file mode 100644 index c33dc58cf2..0000000000 --- a/samples/javaconfig/concurrency/src/main/java/org/springframework/security/samples/config/MessageSecurityWebApplicationInitializer.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.config; - -import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; -import org.springframework.security.web.session.HttpSessionEventPublisher; - -/** - * We customize {@link AbstractSecurityWebApplicationInitializer} to enable the - * {@link HttpSessionEventPublisher}. - * - * @author Rob Winch - */ -public class MessageSecurityWebApplicationInitializer extends - AbstractSecurityWebApplicationInitializer { - - @Override - protected boolean enableHttpSessionEventPublisher() { - return true; - } -} diff --git a/samples/javaconfig/concurrency/src/main/java/org/springframework/security/samples/config/SecurityConfig.java b/samples/javaconfig/concurrency/src/main/java/org/springframework/security/samples/config/SecurityConfig.java deleted file mode 100644 index 45773f3eb7..0000000000 --- a/samples/javaconfig/concurrency/src/main/java/org/springframework/security/samples/config/SecurityConfig.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.config; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -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.WebSecurityConfigurerAdapter; - -import static org.springframework.security.config.Customizer.withDefaults; - -@EnableWebSecurity -@EnableGlobalMethodSecurity(prePostEnabled = true) -public class SecurityConfig extends WebSecurityConfigurerAdapter { - // @formatter:off - @Autowired - public void configureGlobal( - AuthenticationManagerBuilder auth) throws Exception { - auth - .inMemoryAuthentication() - .withUser("user").password("password").roles("USER"); - } - // @formatter:on - - // @formatter:off - @Override - protected void configure( - HttpSecurity http) throws Exception { - http - .authorizeRequests((authorizeRequests) -> - authorizeRequests - .anyRequest().authenticated() - ) - .formLogin(withDefaults()) - .sessionManagement((sessionManagement) -> - sessionManagement - .sessionConcurrency((sessionConcurrency) -> - sessionConcurrency - .maximumSessions(1) - .expiredUrl("/login?expired") - ) - ); - } - // @formatter:on -} diff --git a/samples/javaconfig/concurrency/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java b/samples/javaconfig/concurrency/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java deleted file mode 100644 index dd807f16d1..0000000000 --- a/samples/javaconfig/concurrency/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.config; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Rob Winch - * - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = SecurityConfig.class) -public class SecurityConfigTests { - - @Test - public void securityConfigurationLoads() { - } -} diff --git a/samples/javaconfig/data/spring-security-samples-javaconfig-data.gradle b/samples/javaconfig/data/spring-security-samples-javaconfig-data.gradle deleted file mode 100644 index 94680d9b97..0000000000 --- a/samples/javaconfig/data/spring-security-samples-javaconfig-data.gradle +++ /dev/null @@ -1,12 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-data') - compile 'javax.validation:validation-api' - compile 'org.eclipse.persistence:javax.persistence' - compile 'org.hibernate:hibernate-entitymanager' - compile 'org.hibernate:hibernate-validator' - compile 'org.hsqldb:hsqldb' - compile 'org.springframework.data:spring-data-jpa' -} diff --git a/samples/javaconfig/data/src/main/java/samples/DataConfig.java b/samples/javaconfig/data/src/main/java/samples/DataConfig.java deleted file mode 100644 index cd401a5df4..0000000000 --- a/samples/javaconfig/data/src/main/java/samples/DataConfig.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package samples; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.DependsOn; -import org.springframework.core.io.ClassPathResource; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; -import org.springframework.orm.jpa.vendor.Database; -import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; -import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension; -import org.springframework.transaction.PlatformTransactionManager; -import samples.data.Message; - -import javax.sql.DataSource; - -/** - * @author Rob Winch - */ -@Configuration -@ComponentScan -@EnableJpaRepositories -public class DataConfig { - - @Bean - public SecurityEvaluationContextExtension expressionEvaluationContextProvider() { - return new SecurityEvaluationContextExtension(); - } - - @Bean - public DataSource dataSource() { - EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); - return builder.setType(EmbeddedDatabaseType.HSQL).build(); - } - - @Bean - public LocalContainerEntityManagerFactoryBean entityManagerFactory() { - HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); - vendorAdapter.setDatabase(Database.HSQL); - vendorAdapter.setGenerateDdl(true); - - LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); - factory.setJpaVendorAdapter(vendorAdapter); - factory.setPackagesToScan(Message.class.getPackage().getName()); - factory.setDataSource(dataSource()); - - return factory; - } - - @Bean - @DependsOn("entityManagerFactory") - public ResourceDatabasePopulator initDatabase(DataSource dataSource) throws Exception { - ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); - populator.addScript(new ClassPathResource("data.sql")); - populator.populate(dataSource.getConnection()); - return populator; - } - - @Bean - public PlatformTransactionManager transactionManager() { - JpaTransactionManager txManager = new JpaTransactionManager(); - txManager.setEntityManagerFactory(entityManagerFactory().getObject()); - return txManager; - } -} diff --git a/samples/javaconfig/data/src/main/java/samples/data/Message.java b/samples/javaconfig/data/src/main/java/samples/data/Message.java deleted file mode 100644 index 7c567e9c12..0000000000 --- a/samples/javaconfig/data/src/main/java/samples/data/Message.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package samples.data; - -import java.util.Calendar; - -import javax.persistence.*; - -import org.hibernate.validator.constraints.NotEmpty; - -@Entity -public class Message { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - @NotEmpty(message = "Message is required.") - private String text; - - @NotEmpty(message = "Summary is required.") - private String summary; - - private Calendar created = Calendar.getInstance(); - - @OneToOne - private User to; - - public User getTo() { - return to; - } - - public void setTo(User to) { - this.to = to; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public Calendar getCreated() { - return created; - } - - public void setCreated(Calendar created) { - this.created = created; - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - - public String getSummary() { - return summary; - } - - public void setSummary(String summary) { - this.summary = summary; - } -} diff --git a/samples/javaconfig/data/src/main/java/samples/data/MessageRepository.java b/samples/javaconfig/data/src/main/java/samples/data/MessageRepository.java deleted file mode 100644 index c98a1d3fde..0000000000 --- a/samples/javaconfig/data/src/main/java/samples/data/MessageRepository.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package samples.data; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -/** - * @author Rob Winch - */ -@Repository -public interface MessageRepository extends JpaRepository { -} diff --git a/samples/javaconfig/data/src/main/java/samples/data/SecurityMessageRepository.java b/samples/javaconfig/data/src/main/java/samples/data/SecurityMessageRepository.java deleted file mode 100644 index f6b2ac956d..0000000000 --- a/samples/javaconfig/data/src/main/java/samples/data/SecurityMessageRepository.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package samples.data; - -import org.springframework.data.jpa.repository.Query; -import org.springframework.stereotype.Repository; - -import java.util.List; - -/** - * @author Rob Winch - */ -@Repository -public interface SecurityMessageRepository extends MessageRepository { - @Query("select m from Message m where m.to.id = ?#{ principal?.id }") - List findAll(); -} \ No newline at end of file diff --git a/samples/javaconfig/data/src/main/java/samples/data/User.java b/samples/javaconfig/data/src/main/java/samples/data/User.java deleted file mode 100644 index 15d4f37d77..0000000000 --- a/samples/javaconfig/data/src/main/java/samples/data/User.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package samples.data; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; - -/** - * @author Rob Winch - */ -@Entity -public class User { - @GeneratedValue(strategy = GenerationType.AUTO) - @Id - private Long id; - - private String firstName; - - private String lastName; - - private String email; - - private String password; - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getFirstName() { - return firstName; - } - - public void setFirstName(String firstName) { - this.firstName = firstName; - } - - public String getLastName() { - return lastName; - } - - public void setLastName(String lastName) { - this.lastName = lastName; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } -} \ No newline at end of file diff --git a/samples/javaconfig/data/src/test/java/samples/data/SecurityMessageRepositoryTests.java b/samples/javaconfig/data/src/test/java/samples/data/SecurityMessageRepositoryTests.java deleted file mode 100644 index 9972659fd2..0000000000 --- a/samples/javaconfig/data/src/test/java/samples/data/SecurityMessageRepositoryTests.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2002-2017 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package samples.data; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import samples.DataConfig; - -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Rob Winch - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = DataConfig.class) -public class SecurityMessageRepositoryTests { - @Autowired - SecurityMessageRepository repository; - - User user; - - @Before - public void setup() { - user = new User(); - user.setId(0L); - List authorities = AuthorityUtils - .createAuthorityList("ROLE_USER"); - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( - user, "notused", authorities); - SecurityContextHolder.getContext().setAuthentication(authentication); - } - - @After - public void cleanup() { - SecurityContextHolder.clearContext(); - } - - @Test - public void findAllOnlyToCurrentUser() { - Long expectedId = user.getId(); - List messages = repository.findAll(); - assertThat(messages).hasSize(3); - for (Message m : messages) { - assertThat(m.getTo().getId()).isEqualTo(expectedId); - } - } -} diff --git a/samples/javaconfig/data/src/test/resources/data.sql b/samples/javaconfig/data/src/test/resources/data.sql deleted file mode 100644 index 97c60b155b..0000000000 --- a/samples/javaconfig/data/src/test/resources/data.sql +++ /dev/null @@ -1,10 +0,0 @@ -insert into user(id,email,password,firstName,lastName) values (0,'rob@example.com','password','Rob','Winch'); -insert into user(id,email,password,firstName,lastName) values (1,'luke@example.com','password','Luke','Taylor'); - -insert into message(id,created,to_id,summary,text) values (100,'2014-07-10 10:00:00',0,'Hello Rob','This message is for Rob'); -insert into message(id,created,to_id,summary,text) values (101,'2014-07-10 14:00:00',0,'How are you Rob?','This message is for Rob'); -insert into message(id,created,to_id,summary,text) values (102,'2014-07-11 22:00:00',0,'Is this secure?','This message is for Rob'); - -insert into message(id,created,to_id,summary,text) values (110,'2014-07-12 10:00:00',1,'Hello Luke','This message is for Luke'); -insert into message(id,created,to_id,summary,text) values (111,'2014-07-12 10:00:00',1,'Greetings Luke','This message is for Luke'); -insert into message(id,created,to_id,summary,text) values (112,'2014-07-12 10:00:00',1,'Is this secure?','This message is for Luke'); \ No newline at end of file diff --git a/samples/javaconfig/form/spring-security-samples-javaconfig-form.gradle b/samples/javaconfig/form/spring-security-samples-javaconfig-form.gradle deleted file mode 100644 index 3dee895966..0000000000 --- a/samples/javaconfig/form/spring-security-samples-javaconfig-form.gradle +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -apply plugin: 'io.spring.convention.spring-sample-war' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-core') - compile project(':spring-security-samples-javaconfig-messages') - compile project(':spring-security-web') - compile 'javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api' - compile 'javax.validation:validation-api' - compile 'org.hibernate:hibernate-validator' - compile 'org.springframework:spring-webmvc' - compile slf4jDependencies - - compile 'javax.xml.bind:jaxb-api' - compile 'com.sun.xml.bind:jaxb-core' - compile 'com.sun.xml.bind:jaxb-impl' - - providedCompile 'javax.servlet.jsp:javax.servlet.jsp-api' - providedCompile 'javax.servlet:javax.servlet-api' - - runtime 'opensymphony:sitemesh' - - integrationTestCompile seleniumDependencies -} diff --git a/samples/javaconfig/form/src/integration-test/java/org/springframework/security/samples/FormJcTests.java b/samples/javaconfig/form/src/integration-test/java/org/springframework/security/samples/FormJcTests.java deleted file mode 100644 index 1ca1e669a1..0000000000 --- a/samples/javaconfig/form/src/integration-test/java/org/springframework/security/samples/FormJcTests.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.htmlunit.HtmlUnitDriver; -import org.springframework.security.samples.pages.HomePage; -import org.springframework.security.samples.pages.LoginPage; - -/** - * @author Michael Simons - */ -public class FormJcTests { - private WebDriver driver; - - private int port; - - @Before - public void setup() { - this.port = Integer.parseInt(System.getProperty("app.httpPort")); - this.driver = new HtmlUnitDriver(); - } - - @After - public void tearDown() { - this.driver.quit(); - } - - @Test - public void accessHomePageWithUnauthenticatedUserSendsToLoginPage() { - final LoginPage loginPage = HomePage.to(this.driver, this.port); - loginPage.assertAt(); - } - - @Test - public void authenticatedUserIsSentToOriginalPage() { - final String userName = "user"; - final HomePage homePage = HomePage.to(this.driver, this.port) - .loginForm() - .username(userName) - .password("password") - .submit(); - homePage - .assertAt() - .andTheUserNameDisplayedIs(userName); - } - - @Test - public void authenticatedUserLogsOut() { - LoginPage loginPage = HomePage.to(this.driver, this.port) - .loginForm() - .username("user") - .password("password") - .submit() - .logout(); - loginPage.assertAt(); - - loginPage = HomePage.to(this.driver, this.port); - loginPage.assertAt(); - } -} diff --git a/samples/javaconfig/form/src/integration-test/java/org/springframework/security/samples/pages/HomePage.java b/samples/javaconfig/form/src/integration-test/java/org/springframework/security/samples/pages/HomePage.java deleted file mode 100644 index 22ddd1c639..0000000000 --- a/samples/javaconfig/form/src/integration-test/java/org/springframework/security/samples/pages/HomePage.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.pages; - -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.FindBy; -import org.openqa.selenium.support.PageFactory; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Michael Simons - */ -public class HomePage { - private final WebDriver webDriver; - - @FindBy(css = "input[type=submit]") - private WebElement logoutButton; - - public static LoginPage to(WebDriver driver, int port) { - driver.get("http://localhost:" + port +"/"); - return PageFactory.initElements(driver, LoginPage.class); - } - - public HomePage(WebDriver webDriver) { - this.webDriver = webDriver; - } - - public Content assertAt() { - assertThat(this.webDriver.getTitle()).isEqualTo("SecureMail: View All"); - return PageFactory.initElements(this.webDriver, Content.class); - } - - public LoginPage logout() { - this.logoutButton.submit(); - return PageFactory.initElements(this.webDriver, LoginPage.class); - } - - public static class Content { - @FindBy(css = "p.navbar-text") - private WebElement message; - - public Content andTheUserNameDisplayedIs(final String userName) { - assertThat(message.getText()).isEqualTo(userName); - return this; - } - } -} diff --git a/samples/javaconfig/form/src/integration-test/java/org/springframework/security/samples/pages/LoginPage.java b/samples/javaconfig/form/src/integration-test/java/org/springframework/security/samples/pages/LoginPage.java deleted file mode 100644 index af6fbaa988..0000000000 --- a/samples/javaconfig/form/src/integration-test/java/org/springframework/security/samples/pages/LoginPage.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2002-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.pages; - -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.support.FindBy; -import org.openqa.selenium.support.PageFactory; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Michael Simons - */ -public class LoginPage { - - private final WebDriver webDriver; - - private final LoginForm loginForm; - - public LoginPage(WebDriver webDriver) { - this.webDriver = webDriver; - this.loginForm = PageFactory.initElements(this.webDriver, LoginForm.class); - } - - public LoginPage assertAt() { - assertThat(this.webDriver.getTitle()).isEqualTo("SecureMail: Please Login"); - return this; - } - - public LoginForm loginForm() { - return this.loginForm; - } - - public static class LoginForm { - private WebDriver webDriver; - private WebElement username; - private WebElement password; - @FindBy(css = "button[type=submit]") - private WebElement submit; - - public LoginForm(WebDriver webDriver) { - this.webDriver = webDriver; - } - - public LoginForm username(String username) { - this.username.sendKeys(username); - return this; - } - - public LoginForm password(String password) { - this.password.sendKeys(password); - return this; - } - - public HomePage submit() { - this.submit.click(); - return PageFactory.initElements(this.webDriver, HomePage.class); - } - } -} diff --git a/samples/javaconfig/form/src/main/java/org/springframework/security/samples/config/MessageSecurityWebApplicationInitializer.java b/samples/javaconfig/form/src/main/java/org/springframework/security/samples/config/MessageSecurityWebApplicationInitializer.java deleted file mode 100644 index f851f82de0..0000000000 --- a/samples/javaconfig/form/src/main/java/org/springframework/security/samples/config/MessageSecurityWebApplicationInitializer.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.config; - -import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; - -/** - * No customizations of {@link AbstractSecurityWebApplicationInitializer} are necessary. - * - * @author Rob Winch - */ -public class MessageSecurityWebApplicationInitializer extends - AbstractSecurityWebApplicationInitializer { -} diff --git a/samples/javaconfig/form/src/main/java/org/springframework/security/samples/config/SecurityConfig.java b/samples/javaconfig/form/src/main/java/org/springframework/security/samples/config/SecurityConfig.java deleted file mode 100644 index 8f9cbba6f6..0000000000 --- a/samples/javaconfig/form/src/main/java/org/springframework/security/samples/config/SecurityConfig.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2002-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.config; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -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.WebSecurityConfigurerAdapter; -import org.springframework.security.core.userdetails.User; - -@EnableWebSecurity -public class SecurityConfig extends WebSecurityConfigurerAdapter { - - // @formatter:off - @Override - protected void configure(HttpSecurity http) throws Exception { - http - .authorizeRequests((authorizeRequests) -> - authorizeRequests - .antMatchers("/resources/**").permitAll() - .anyRequest().authenticated() - ) - .formLogin((formLogin) -> - formLogin - .loginPage("/login") - .permitAll() - ) - .logout((logout) -> - logout - .permitAll() - ); - } - // @formatter:on - - // @formatter:off - @Autowired - public void configureGlobal( - AuthenticationManagerBuilder auth) throws Exception { - auth - .inMemoryAuthentication() - .withUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER")); - } - // @formatter:on -} diff --git a/samples/javaconfig/form/src/main/resources/logback.xml b/samples/javaconfig/form/src/main/resources/logback.xml deleted file mode 100644 index 3ebbcc0ddd..0000000000 --- a/samples/javaconfig/form/src/main/resources/logback.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - diff --git a/samples/javaconfig/form/src/main/resources/views/login.html b/samples/javaconfig/form/src/main/resources/views/login.html deleted file mode 100644 index c28c5b2add..0000000000 --- a/samples/javaconfig/form/src/main/resources/views/login.html +++ /dev/null @@ -1,24 +0,0 @@ - - - Please Login - - -
-
-
- Please Login -
Invalid - username and password.
-
You - have been logged out.
- - -
- -
-
-
-
- - \ No newline at end of file diff --git a/samples/javaconfig/form/src/main/webapp/WEB-INF/views/login.jspx b/samples/javaconfig/form/src/main/webapp/WEB-INF/views/login.jspx deleted file mode 100644 index 1f472ba566..0000000000 --- a/samples/javaconfig/form/src/main/webapp/WEB-INF/views/login.jspx +++ /dev/null @@ -1,36 +0,0 @@ - - - - -Please Login - - - - -
- Please Login - -
- Invalid username and password. -
-
- -
- You have been logged out. -
-
- - - - -
- -
-
-
- - -
diff --git a/samples/javaconfig/form/src/main/webapp/WEB-INF/views/messages/compose.jspx b/samples/javaconfig/form/src/main/webapp/WEB-INF/views/messages/compose.jspx deleted file mode 100644 index a92f7e2d6c..0000000000 --- a/samples/javaconfig/form/src/main/webapp/WEB-INF/views/messages/compose.jspx +++ /dev/null @@ -1,26 +0,0 @@ - - - - - Compose - - -
-

Messages : Create

- - - - - - -
- -
-
-
- - -
\ No newline at end of file diff --git a/samples/javaconfig/form/src/main/webapp/WEB-INF/views/messages/inbox.jspx b/samples/javaconfig/form/src/main/webapp/WEB-INF/views/messages/inbox.jspx deleted file mode 100644 index ed02d313c6..0000000000 --- a/samples/javaconfig/form/src/main/webapp/WEB-INF/views/messages/inbox.jspx +++ /dev/null @@ -1,40 +0,0 @@ - - - - - Inbox - - -

Inbox

- - - - - - - - - - - - - - - - - - - - - - - -
CreatedSummary
You have not received any mail yet.
- - -
\ No newline at end of file diff --git a/samples/javaconfig/form/src/main/webapp/WEB-INF/views/messages/show.jspx b/samples/javaconfig/form/src/main/webapp/WEB-INF/views/messages/show.jspx deleted file mode 100644 index 82007c267b..0000000000 --- a/samples/javaconfig/form/src/main/webapp/WEB-INF/views/messages/show.jspx +++ /dev/null @@ -1,24 +0,0 @@ - - - - - <c:out value="${message.summary}"/> - - -
-

Message :

-
-
Created
-
-
Message
-
-
-
- - -
\ No newline at end of file diff --git a/samples/javaconfig/form/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java b/samples/javaconfig/form/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java deleted file mode 100644 index dd807f16d1..0000000000 --- a/samples/javaconfig/form/src/test/java/org/springframework/security/samples/config/SecurityConfigTests.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.config; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -/** - * @author Rob Winch - * - */ -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = SecurityConfig.class) -public class SecurityConfigTests { - - @Test - public void securityConfigurationLoads() { - } -} diff --git a/samples/javaconfig/hellojs/spring-security-samples-javaconfig-hellojs.gradle b/samples/javaconfig/hellojs/spring-security-samples-javaconfig-hellojs.gradle deleted file mode 100644 index 86700d410d..0000000000 --- a/samples/javaconfig/hellojs/spring-security-samples-javaconfig-hellojs.gradle +++ /dev/null @@ -1,20 +0,0 @@ -apply plugin: 'io.spring.convention.spring-sample-war' - -dependencies { - compile project(':spring-security-config') - compile project(':spring-security-core') - compile project(':spring-security-samples-javaconfig-messages') - compile project(':spring-security-web') - compile 'com.fasterxml.jackson.core:jackson-databind' - compile 'javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api' - compile 'javax.validation:validation-api' - compile 'org.hibernate:hibernate-validator' - compile 'org.springframework:spring-jdbc' - compile 'org.springframework:spring-webmvc' - compile slf4jDependencies - - providedCompile 'javax.servlet:javax.servlet-api' - providedCompile 'javax.servlet.jsp:javax.servlet.jsp-api' - - runtime 'opensymphony:sitemesh' -} diff --git a/samples/javaconfig/hellojs/src/main/java/org/springframework/security/samples/config/MessageSecurityWebApplicationInitializer.java b/samples/javaconfig/hellojs/src/main/java/org/springframework/security/samples/config/MessageSecurityWebApplicationInitializer.java deleted file mode 100644 index f851f82de0..0000000000 --- a/samples/javaconfig/hellojs/src/main/java/org/springframework/security/samples/config/MessageSecurityWebApplicationInitializer.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2002-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.config; - -import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer; - -/** - * No customizations of {@link AbstractSecurityWebApplicationInitializer} are necessary. - * - * @author Rob Winch - */ -public class MessageSecurityWebApplicationInitializer extends - AbstractSecurityWebApplicationInitializer { -} diff --git a/samples/javaconfig/hellojs/src/main/java/org/springframework/security/samples/config/SecurityConfig.java b/samples/javaconfig/hellojs/src/main/java/org/springframework/security/samples/config/SecurityConfig.java deleted file mode 100644 index 595d2413e0..0000000000 --- a/samples/javaconfig/hellojs/src/main/java/org/springframework/security/samples/config/SecurityConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.config; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; - -@EnableWebSecurity -public class SecurityConfig { - - // @formatter:off - @Autowired - public void configureGlobal( - AuthenticationManagerBuilder auth) throws Exception { - auth - .inMemoryAuthentication() - .withUser("user").password("{noop}password").roles("USER"); - } - // @formatter:on -} diff --git a/samples/javaconfig/hellojs/src/main/java/org/springframework/security/samples/mvc/MessageJsonController.java b/samples/javaconfig/hellojs/src/main/java/org/springframework/security/samples/mvc/MessageJsonController.java deleted file mode 100644 index 696d3c75e7..0000000000 --- a/samples/javaconfig/hellojs/src/main/java/org/springframework/security/samples/mvc/MessageJsonController.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.security.samples.mvc; - -import java.util.ArrayList; -import java.util.Calendar; -import java.util.List; -import java.util.Optional; - -import javax.validation.Valid; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.samples.data.Message; -import org.springframework.security.samples.data.MessageRepository; -import org.springframework.stereotype.Controller; -import org.springframework.validation.BindingResult; -import org.springframework.validation.ObjectError; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.servlet.mvc.support.RedirectAttributes; - -@Controller -@RequestMapping(value = "/", produces = "application/json") -public class MessageJsonController { - private MessageRepository messageRepository; - - @Autowired - public MessageJsonController(MessageRepository messageRepository) { - this.messageRepository = messageRepository; - } - - @RequestMapping - public ResponseEntity> list() { - Iterable messages = messageRepository.findAll(); - return new ResponseEntity<>(messages, HttpStatus.OK); - } - - @RequestMapping("{id}") - public ResponseEntity> view(@PathVariable Long id) { - Optional message = messageRepository.findById(id); - return new ResponseEntity<>(message, HttpStatus.OK); - } - - @RequestMapping(method = RequestMethod.POST, consumes = "application/json") - public ResponseEntity create(@Valid @RequestBody Message message, - BindingResult result, RedirectAttributes redirect) { - if (result.hasErrors()) { - List errors = new ArrayList<>(result.getErrorCount()); - for (ObjectError r : result.getAllErrors()) { - errors.add(r.getDefaultMessage()); - } - return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST); - } - message.setCreated(Calendar.getInstance()); - message = messageRepository.save(message); - return new ResponseEntity<>(message, HttpStatus.OK); - } -} diff --git a/samples/javaconfig/hellojs/src/main/resources/resources/js/bootstrap.js b/samples/javaconfig/hellojs/src/main/resources/resources/js/bootstrap.js deleted file mode 100644 index ee5a14587b..0000000000 --- a/samples/javaconfig/hellojs/src/main/resources/resources/js/bootstrap.js +++ /dev/null @@ -1,2280 +0,0 @@ -/* =================================================== - * bootstrap-transition.js v2.3.2 - * https://twitter.github.com/bootstrap/javascript.html#transitions - * =================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* CSS TRANSITION SUPPORT (https://www.modernizr.com/) - * ======================================================= */ - - $(function () { - - $.support.transition = (function () { - - var transitionEnd = (function () { - - var el = document.createElement('bootstrap') - , transEndEventNames = { - 'WebkitTransition' : 'webkitTransitionEnd' - , 'MozTransition' : 'transitionend' - , 'OTransition' : 'oTransitionEnd otransitionend' - , 'transition' : 'transitionend' - } - , name - - for (name in transEndEventNames){ - if (el.style[name] !== undefined) { - return transEndEventNames[name] - } - } - - }()) - - return transitionEnd && { - end: transitionEnd - } - - })() - - }) - -}(window.jQuery);/* ========================================================== - * bootstrap-alert.js v2.3.2 - * https://twitter.github.com/bootstrap/javascript.html#alerts - * ========================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* ALERT CLASS DEFINITION - * ====================== */ - - var dismiss = '[data-dismiss="alert"]' - , Alert = function (el) { - $(el).on('click', dismiss, this.close) - } - - Alert.prototype.close = function (e) { - var $this = $(this) - , selector = $this.attr('data-target') - , $parent - - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 - } - - $parent = $(selector) - - e && e.preventDefault() - - $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) - - $parent.trigger(e = $.Event('close')) - - if (e.isDefaultPrevented()) return - - $parent.removeClass('in') - - function removeElement() { - $parent - .trigger('closed') - .remove() - } - - $.support.transition && $parent.hasClass('fade') ? - $parent.on($.support.transition.end, removeElement) : - removeElement() - } - - - /* ALERT PLUGIN DEFINITION - * ======================= */ - - var old = $.fn.alert - - $.fn.alert = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('alert') - if (!data) $this.data('alert', (data = new Alert(this))) - if (typeof option == 'string') data[option].call($this) - }) - } - - $.fn.alert.Constructor = Alert - - - /* ALERT NO CONFLICT - * ================= */ - - $.fn.alert.noConflict = function () { - $.fn.alert = old - return this - } - - - /* ALERT DATA-API - * ============== */ - - $(document).on('click.alert.data-api', dismiss, Alert.prototype.close) - -}(window.jQuery);/* ============================================================ - * bootstrap-button.js v2.3.2 - * https://twitter.github.com/bootstrap/javascript.html#buttons - * ============================================================ - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* BUTTON PUBLIC CLASS DEFINITION - * ============================== */ - - var Button = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, $.fn.button.defaults, options) - } - - Button.prototype.setState = function (state) { - var d = 'disabled' - , $el = this.$element - , data = $el.data() - , val = $el.is('input') ? 'val' : 'html' - - state = state + 'Text' - data.resetText || $el.data('resetText', $el[val]()) - - $el[val](data[state] || this.options[state]) - - // push to event loop to allow forms to submit - setTimeout(function () { - state == 'loadingText' ? - $el.addClass(d).attr(d, d) : - $el.removeClass(d).removeAttr(d) - }, 0) - } - - Button.prototype.toggle = function () { - var $parent = this.$element.closest('[data-toggle="buttons-radio"]') - - $parent && $parent - .find('.active') - .removeClass('active') - - this.$element.toggleClass('active') - } - - - /* BUTTON PLUGIN DEFINITION - * ======================== */ - - var old = $.fn.button - - $.fn.button = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('button') - , options = typeof option == 'object' && option - if (!data) $this.data('button', (data = new Button(this, options))) - if (option == 'toggle') data.toggle() - else if (option) data.setState(option) - }) - } - - $.fn.button.defaults = { - loadingText: 'loading...' - } - - $.fn.button.Constructor = Button - - - /* BUTTON NO CONFLICT - * ================== */ - - $.fn.button.noConflict = function () { - $.fn.button = old - return this - } - - - /* BUTTON DATA-API - * =============== */ - - $(document).on('click.button.data-api', '[data-toggle^=button]', function (e) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - $btn.button('toggle') - }) - -}(window.jQuery);/* ========================================================== - * bootstrap-carousel.js v2.3.2 - * https://twitter.github.com/bootstrap/javascript.html#carousel - * ========================================================== - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================== */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* CAROUSEL CLASS DEFINITION - * ========================= */ - - var Carousel = function (element, options) { - this.$element = $(element) - this.$indicators = this.$element.find('.carousel-indicators') - this.options = options - this.options.pause == 'hover' && this.$element - .on('mouseenter', $.proxy(this.pause, this)) - .on('mouseleave', $.proxy(this.cycle, this)) - } - - Carousel.prototype = { - - cycle: function (e) { - if (!e) this.paused = false - if (this.interval) clearInterval(this.interval); - this.options.interval - && !this.paused - && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) - return this - } - - , getActiveIndex: function () { - this.$active = this.$element.find('.item.active') - this.$items = this.$active.parent().children() - return this.$items.index(this.$active) - } - - , to: function (pos) { - var activeIndex = this.getActiveIndex() - , that = this - - if (pos > (this.$items.length - 1) || pos < 0) return - - if (this.sliding) { - return this.$element.one('slid', function () { - that.to(pos) - }) - } - - if (activeIndex == pos) { - return this.pause().cycle() - } - - return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) - } - - , pause: function (e) { - if (!e) this.paused = true - if (this.$element.find('.next, .prev').length && $.support.transition.end) { - this.$element.trigger($.support.transition.end) - this.cycle(true) - } - clearInterval(this.interval) - this.interval = null - return this - } - - , next: function () { - if (this.sliding) return - return this.slide('next') - } - - , prev: function () { - if (this.sliding) return - return this.slide('prev') - } - - , slide: function (type, next) { - var $active = this.$element.find('.item.active') - , $next = next || $active[type]() - , isCycling = this.interval - , direction = type == 'next' ? 'left' : 'right' - , fallback = type == 'next' ? 'first' : 'last' - , that = this - , e - - this.sliding = true - - isCycling && this.pause() - - $next = $next.length ? $next : this.$element.find('.item')[fallback]() - - e = $.Event('slide', { - relatedTarget: $next[0] - , direction: direction - }) - - if ($next.hasClass('active')) return - - if (this.$indicators.length) { - this.$indicators.find('.active').removeClass('active') - this.$element.one('slid', function () { - var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) - $nextIndicator && $nextIndicator.addClass('active') - }) - } - - if ($.support.transition && this.$element.hasClass('slide')) { - this.$element.trigger(e) - if (e.isDefaultPrevented()) return - $next.addClass(type) - $next[0].offsetWidth // force reflow - $active.addClass(direction) - $next.addClass(direction) - this.$element.one($.support.transition.end, function () { - $next.removeClass([type, direction].join(' ')).addClass('active') - $active.removeClass(['active', direction].join(' ')) - that.sliding = false - setTimeout(function () { that.$element.trigger('slid') }, 0) - }) - } else { - this.$element.trigger(e) - if (e.isDefaultPrevented()) return - $active.removeClass('active') - $next.addClass('active') - this.sliding = false - this.$element.trigger('slid') - } - - isCycling && this.cycle() - - return this - } - - } - - - /* CAROUSEL PLUGIN DEFINITION - * ========================== */ - - var old = $.fn.carousel - - $.fn.carousel = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('carousel') - , options = $.extend({}, $.fn.carousel.defaults, typeof option == 'object' && option) - , action = typeof option == 'string' ? option : options.slide - if (!data) $this.data('carousel', (data = new Carousel(this, options))) - if (typeof option == 'number') data.to(option) - else if (action) data[action]() - else if (options.interval) data.pause().cycle() - }) - } - - $.fn.carousel.defaults = { - interval: 5000 - , pause: 'hover' - } - - $.fn.carousel.Constructor = Carousel - - - /* CAROUSEL NO CONFLICT - * ==================== */ - - $.fn.carousel.noConflict = function () { - $.fn.carousel = old - return this - } - - /* CAROUSEL DATA-API - * ================= */ - - $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { - var $this = $(this), href - , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 - , options = $.extend({}, $target.data(), $this.data()) - , slideIndex - - $target.carousel(options) - - if (slideIndex = $this.attr('data-slide-to')) { - $target.data('carousel').pause().to(slideIndex).cycle() - } - - e.preventDefault() - }) - -}(window.jQuery);/* ============================================================= - * bootstrap-collapse.js v2.3.2 - * https://twitter.github.com/bootstrap/javascript.html#collapse - * ============================================================= - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* COLLAPSE PUBLIC CLASS DEFINITION - * ================================ */ - - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, $.fn.collapse.defaults, options) - - if (this.options.parent) { - this.$parent = $(this.options.parent) - } - - this.options.toggle && this.toggle() - } - - Collapse.prototype = { - - constructor: Collapse - - , dimension: function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } - - , show: function () { - var dimension - , scroll - , actives - , hasData - - if (this.transitioning || this.$element.hasClass('in')) return - - dimension = this.dimension() - scroll = $.camelCase(['scroll', dimension].join('-')) - actives = this.$parent && this.$parent.find('> .accordion-group > .in') - - if (actives && actives.length) { - hasData = actives.data('collapse') - if (hasData && hasData.transitioning) return - actives.collapse('hide') - hasData || actives.data('collapse', null) - } - - this.$element[dimension](0) - this.transition('addClass', $.Event('show'), 'shown') - $.support.transition && this.$element[dimension](this.$element[0][scroll]) - } - - , hide: function () { - var dimension - if (this.transitioning || !this.$element.hasClass('in')) return - dimension = this.dimension() - this.reset(this.$element[dimension]()) - this.transition('removeClass', $.Event('hide'), 'hidden') - this.$element[dimension](0) - } - - , reset: function (size) { - var dimension = this.dimension() - - this.$element - .removeClass('collapse') - [dimension](size || 'auto') - [0].offsetWidth - - this.$element[size !== null ? 'addClass' : 'removeClass']('collapse') - - return this - } - - , transition: function (method, startEvent, completeEvent) { - var that = this - , complete = function () { - if (startEvent.type == 'show') that.reset() - that.transitioning = 0 - that.$element.trigger(completeEvent) - } - - this.$element.trigger(startEvent) - - if (startEvent.isDefaultPrevented()) return - - this.transitioning = 1 - - this.$element[method]('in') - - $.support.transition && this.$element.hasClass('collapse') ? - this.$element.one($.support.transition.end, complete) : - complete() - } - - , toggle: function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } - - } - - - /* COLLAPSE PLUGIN DEFINITION - * ========================== */ - - var old = $.fn.collapse - - $.fn.collapse = function (option) { - return this.each(function () { - var $this = $(this) - , data = $this.data('collapse') - , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option) - if (!data) $this.data('collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } - - $.fn.collapse.defaults = { - toggle: true - } - - $.fn.collapse.Constructor = Collapse - - - /* COLLAPSE NO CONFLICT - * ==================== */ - - $.fn.collapse.noConflict = function () { - $.fn.collapse = old - return this - } - - - /* COLLAPSE DATA-API - * ================= */ - - $(document).on('click.collapse.data-api', '[data-toggle=collapse]', function (e) { - var $this = $(this), href - , target = $this.attr('data-target') - || e.preventDefault() - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 - , option = $(target).data('collapse') ? 'toggle' : $this.data() - $this[$(target).hasClass('in') ? 'addClass' : 'removeClass']('collapsed') - $(target).collapse(option) - }) - -}(window.jQuery);/* ============================================================ - * bootstrap-dropdown.js v2.3.2 - * https://twitter.github.com/bootstrap/javascript.html#dropdowns - * ============================================================ - * Copyright 2012 Twitter, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============================================================ */ - - -!function ($) { - - "use strict"; // jshint ;_; - - - /* DROPDOWN CLASS DEFINITION - * ========================= */ - - var toggle = '[data-toggle=dropdown]' - , Dropdown = function (element) { - var $el = $(element).on('click.dropdown.data-api', this.toggle) - $('html').on('click.dropdown.data-api', function () { - $el.parent().removeClass('open') - }) - } - - Dropdown.prototype = { - - constructor: Dropdown - - , toggle: function (e) { - var $this = $(this) - , $parent - , isActive - - if ($this.is('.disabled, :disabled')) return - - $parent = getParent($this) - - isActive = $parent.hasClass('open') - - clearMenus() - - if (!isActive) { - if ('ontouchstart' in document.documentElement) { - // if mobile we we use a backdrop because click events don't delegate - $('