Explorar o código

Refresh Getting Started example

Closes gh-1186
Steve Riesenberg %!s(int64=2) %!d(string=hai) anos
pai
achega
2814bc31b8

+ 8 - 12
docs/src/docs/asciidoc/examples/src/main/java/sample/gettingStarted/SecurityConfig.java

@@ -32,7 +32,7 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.core.annotation.Order;
 import org.springframework.security.config.Customizer;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.core.userdetails.User;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UserDetailsService;
@@ -52,6 +52,7 @@ import org.springframework.security.web.SecurityFilterChain;
 import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
 
 @Configuration
+@EnableWebSecurity
 public class SecurityConfig {
 
 	@Bean // <1>
@@ -70,7 +71,7 @@ public class SecurityConfig {
 					new LoginUrlAuthenticationEntryPoint("/login"))
 			)
 			// Accept access tokens for User Info and/or Client Registration
-			.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
+			.oauth2ResourceServer((oauth2) -> oauth2.jwt(Customizer.withDefaults()));
 		// @formatter:on
 
 		return http.build();
@@ -109,26 +110,21 @@ public class SecurityConfig {
 	@Bean // <4>
 	public RegisteredClientRepository registeredClientRepository() {
 		// @formatter:off
-		RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
-				.clientId("messaging-client")
+		RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString())
+				.clientId("oidc-client")
 				.clientSecret("{noop}secret")
 				.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
 				.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
 				.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
-				.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
-				.authorizationGrantType(AuthorizationGrantType.DEVICE_CODE)
-				.redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc")
-				.redirectUri("http://127.0.0.1:8080/authorized")
-				.postLogoutRedirectUri("http://127.0.0.1:8080/index")
+				.redirectUri("http://127.0.0.1:8080/login/oauth2/code/oidc-client")
+				.postLogoutRedirectUri("http://127.0.0.1:8080/")
 				.scope(OidcScopes.OPENID)
 				.scope(OidcScopes.PROFILE)
-				.scope("message.read")
-				.scope("message.write")
 				.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
 				.build();
 		// @formatter:on
 
-		return new InMemoryRegisteredClientRepository(registeredClient);
+		return new InMemoryRegisteredClientRepository(oidcClient);
 	}
 
 	@Bean // <5>

+ 29 - 0
docs/src/docs/asciidoc/examples/src/main/java/sample/gettingStarted/application.yml

@@ -0,0 +1,29 @@
+server:
+  port: 9000
+
+logging:
+  level:
+    org.springframework.security: trace
+
+spring:
+  security:
+    oauth2:
+      authorizationserver:
+        client:
+          oidc-client:
+            registration:
+              client-id: "oidc-client"
+              client-secret: "{noop}secret"
+              client-authentication-methods:
+                - "client_secret_basic"
+              authorization-grant-types:
+                - "authorization_code"
+                - "refresh_token"
+              redirect-uris:
+                - "http://127.0.0.1:8080/login/oauth2/code/oidc-client"
+              post-logout-redirect-uris:
+                - "http://127.0.0.1:8080/"
+              scopes:
+                - "openid"
+                - "profile"
+            require-authorization-consent: true

+ 1 - 1
docs/src/docs/asciidoc/examples/src/test/java/sample/AuthorizationCodeGrantFlow.java

@@ -127,7 +127,7 @@ public class AuthorizationCodeGrantFlow {
 				.andReturn();
 		String redirectedUrl = mvcResult.getResponse().getRedirectedUrl();
 		assertThat(redirectedUrl).isNotNull();
-		assertThat(redirectedUrl).matches("http://127.0.0.1:8080/authorized\\?code=.{15,}&state=state");
+		assertThat(redirectedUrl).matches("http://127.0.0.1:8080/\\S+\\?code=.{15,}&state=state");
 
 		String locationHeader = URLDecoder.decode(redirectedUrl, StandardCharsets.UTF_8.name());
 		UriComponents uriComponents = UriComponentsBuilder.fromUriString(locationHeader).build();

+ 4 - 51
docs/src/docs/asciidoc/examples/src/test/java/sample/gettingStarted/SecurityConfigTests.java

@@ -21,7 +21,6 @@ import org.assertj.core.api.ObjectAssert;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import sample.AuthorizationCodeGrantFlow;
-import sample.DeviceAuthorizationGrantFlow;
 import sample.test.SpringTestContext;
 import sample.test.SpringTestContextExtension;
 
@@ -32,6 +31,7 @@ import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Import;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
+import org.springframework.security.oauth2.core.oidc.OidcScopes;
 import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames;
 import org.springframework.security.oauth2.server.authorization.InMemoryOAuth2AuthorizationConsentService;
 import org.springframework.security.oauth2.server.authorization.InMemoryOAuth2AuthorizationService;
@@ -77,13 +77,13 @@ public class SecurityConfigTests {
 		assertThat(this.authorizationService).isInstanceOf(InMemoryOAuth2AuthorizationService.class);
 		assertThat(this.authorizationConsentService).isInstanceOf(InMemoryOAuth2AuthorizationConsentService.class);
 
-		RegisteredClient registeredClient = this.registeredClientRepository.findByClientId("messaging-client");
+		RegisteredClient registeredClient = this.registeredClientRepository.findByClientId("oidc-client");
 		assertThat(registeredClient).isNotNull();
 
 		AuthorizationCodeGrantFlow authorizationCodeGrantFlow = new AuthorizationCodeGrantFlow(this.mockMvc);
 		authorizationCodeGrantFlow.setUsername("user");
-		authorizationCodeGrantFlow.addScope("message.read");
-		authorizationCodeGrantFlow.addScope("message.write");
+		authorizationCodeGrantFlow.addScope(OidcScopes.OPENID);
+		authorizationCodeGrantFlow.addScope(OidcScopes.PROFILE);
 
 		String state = authorizationCodeGrantFlow.authorize(registeredClient);
 		assertThatAuthorization(state, OAuth2ParameterNames.STATE).isNotNull();
@@ -117,53 +117,6 @@ public class SecurityConfigTests {
 				StringUtils.delimitedListToStringArray(scopes, " "));
 	}
 
-	@Test
-	public void deviceAuthorizationWhenGettingStartedConfigUsedThenSuccess() throws Exception {
-		this.spring.register(AuthorizationServerConfig.class).autowire();
-		assertThat(this.registeredClientRepository).isInstanceOf(InMemoryRegisteredClientRepository.class);
-		assertThat(this.authorizationService).isInstanceOf(InMemoryOAuth2AuthorizationService.class);
-		assertThat(this.authorizationConsentService).isInstanceOf(InMemoryOAuth2AuthorizationConsentService.class);
-
-		RegisteredClient registeredClient = this.registeredClientRepository.findByClientId("messaging-client");
-		assertThat(registeredClient).isNotNull();
-
-		DeviceAuthorizationGrantFlow deviceAuthorizationGrantFlow = new DeviceAuthorizationGrantFlow(this.mockMvc);
-		deviceAuthorizationGrantFlow.setUsername("user");
-		deviceAuthorizationGrantFlow.addScope("message.read");
-		deviceAuthorizationGrantFlow.addScope("message.write");
-
-		Map<String, Object> deviceAuthorizationResponse = deviceAuthorizationGrantFlow.authorize(registeredClient);
-		String userCode = (String) deviceAuthorizationResponse.get(OAuth2ParameterNames.USER_CODE);
-		assertThatAuthorization(userCode, OAuth2ParameterNames.USER_CODE).isNotNull();
-		assertThatAuthorization(userCode, null).isNotNull();
-
-		String deviceCode = (String) deviceAuthorizationResponse.get(OAuth2ParameterNames.DEVICE_CODE);
-		assertThatAuthorization(deviceCode, OAuth2ParameterNames.DEVICE_CODE).isNotNull();
-		assertThatAuthorization(deviceCode, null).isNotNull();
-
-		String state = deviceAuthorizationGrantFlow.submitCode(userCode);
-		assertThatAuthorization(state, OAuth2ParameterNames.STATE).isNotNull();
-		assertThatAuthorization(state, null).isNotNull();
-
-		deviceAuthorizationGrantFlow.submitConsent(registeredClient, state, userCode);
-
-		Map<String, Object> tokenResponse = deviceAuthorizationGrantFlow.getTokenResponse(registeredClient, deviceCode);
-		String accessToken = (String) tokenResponse.get(OAuth2ParameterNames.ACCESS_TOKEN);
-		assertThatAuthorization(accessToken, OAuth2ParameterNames.ACCESS_TOKEN).isNotNull();
-		assertThatAuthorization(accessToken, null).isNotNull();
-
-		String refreshToken = (String) tokenResponse.get(OAuth2ParameterNames.REFRESH_TOKEN);
-		assertThatAuthorization(refreshToken, OAuth2ParameterNames.REFRESH_TOKEN).isNotNull();
-		assertThatAuthorization(refreshToken, null).isNotNull();
-
-		String scopes = (String) tokenResponse.get(OAuth2ParameterNames.SCOPE);
-		OAuth2AuthorizationConsent authorizationConsent = this.authorizationConsentService.findById(
-				registeredClient.getId(), "user");
-		assertThat(authorizationConsent).isNotNull();
-		assertThat(authorizationConsent.getScopes()).containsExactlyInAnyOrder(
-				StringUtils.delimitedListToStringArray(scopes, " "));
-	}
-
 	private ObjectAssert<OAuth2Authorization> assertThatAuthorization(String token, String tokenType) {
 		return assertThat(findAuthorization(token, tokenType));
 	}

+ 39 - 4
docs/src/docs/asciidoc/getting-started.adoc

@@ -15,7 +15,28 @@ Spring Authorization Server can be used anywhere you already use https://docs.sp
 
 The easiest way to begin using Spring Authorization Server is by creating a https://spring.io/projects/spring-boot[Spring Boot]-based application.
 You can use https://start.spring.io[start.spring.io] to generate a basic project or use the https://github.com/spring-projects/spring-authorization-server/tree/main/samples/default-authorizationserver[default authorization server sample] as a guide.
-Then add Spring Authorization Server as a dependency, as in the following example:
+Then add Spring Boot's starter for Spring Authorization Server as a dependency:
+
+[[spring-boot-maven-dependency]]
+.Maven
+[source,xml,role="primary",subs="attributes,verbatim"]
+----
+<dependency>
+    <groupId>org.springframework.boot</groupId>
+    <artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
+</dependency>
+----
+
+[[spring-boot-gradle-dependency]]
+.Gradle
+[source,gradle,role="secondary",subs="attributes,verbatim"]
+----
+implementation "org.springframework.boot:spring-boot-starter-oauth2-authorization-server"
+----
+
+TIP: See https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started.html#getting-started.installing[Installing Spring Boot] for more information on using Spring Boot with Maven or Gradle.
+
+Alternatively, you can add Spring Authorization Server without Spring Boot using the following example:
 
 [[maven-dependency]]
 .Maven
@@ -35,15 +56,29 @@ Then add Spring Authorization Server as a dependency, as in the following exampl
 implementation "org.springframework.security:spring-security-oauth2-authorization-server:{spring-authorization-server-version}"
 ----
 
-TIP: See https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started.html#getting-started.installing[Installing Spring Boot] for more information on using Spring Boot with Maven or Gradle.
-
 [[developing-your-first-application]]
 == Developing Your First Application
 
-To get started, you need the minimum required components defined as a `@Bean` in a Spring `@Configuration`. These components can be defined as follows:
+To get started, you need the minimum required components defined as a `@Bean`. When using the `spring-boot-starter-oauth2-authorization-server` dependency, define the following properties and Spring Boot will provide the necessary `@Bean` definitions for you:
+
+[[application-yml]]
+.application.yml
+[source,yaml]
+----
+include::{docs-java}/sample/gettingStarted/application.yml[]
+----
+
+TIP: Beyond the Getting Started experience, most users will want to customize the default configuration. The <<defining-required-components,next section>> demonstrates providing all of the necessary beans yourself.
+
+[[defining-required-components]]
+== Defining Required Components
+
+If you want to customize the default configuration (regardless of whether you're using Spring Boot), you can define the minimum required components as a `@Bean` in a Spring `@Configuration`.
 
 TIP: To skip the setup and run a working example, see the https://github.com/spring-projects/spring-authorization-server/tree/main/samples/default-authorizationserver[default authorization server sample].
 
+These components can be defined as follows:
+
 [[sample.gettingStarted]]
 include::code:SecurityConfig[]