Эх сурвалжийг харах

Merge device-grant-authorizationserver into featured-authorizationserver

Issue gh-1189
Joe Grandja 2 жил өмнө
parent
commit
9f1a6e386f
16 өөрчлөгдсөн 55 нэмэгдсэн , 311 устгасан
  1. 0 1
      samples/device-grant-authorizationserver/gradle.properties
  2. 0 29
      samples/device-grant-authorizationserver/samples-device-grant-authorizationserver.gradle
  3. 0 32
      samples/device-grant-authorizationserver/src/main/java/sample/DeviceGrantAuthorizationServerApplication.java
  4. 0 237
      samples/device-grant-authorizationserver/src/main/java/sample/config/SecurityConfig.java
  5. 0 6
      samples/device-grant-authorizationserver/src/main/resources/application.yml
  6. 0 0
      samples/featured-authorizationserver/src/main/java/sample/authentication/DeviceClientAuthenticationProvider.java
  7. 0 0
      samples/featured-authorizationserver/src/main/java/sample/authentication/DeviceClientAuthenticationToken.java
  8. 53 5
      samples/featured-authorizationserver/src/main/java/sample/config/AuthorizationServerConfig.java
  9. 1 1
      samples/featured-authorizationserver/src/main/java/sample/web/DeviceController.java
  10. 0 0
      samples/featured-authorizationserver/src/main/java/sample/web/DeviceErrorController.java
  11. 1 0
      samples/featured-authorizationserver/src/main/java/sample/web/authentication/DeviceClientAuthenticationConverter.java
  12. 0 0
      samples/featured-authorizationserver/src/main/resources/static/assets/css/style.css
  13. 0 0
      samples/featured-authorizationserver/src/main/resources/templates/access-denied.html
  14. 0 0
      samples/featured-authorizationserver/src/main/resources/templates/activate.html
  15. 0 0
      samples/featured-authorizationserver/src/main/resources/templates/activated.html
  16. 0 0
      samples/featured-authorizationserver/src/main/resources/templates/error.html

+ 0 - 1
samples/device-grant-authorizationserver/gradle.properties

@@ -1 +0,0 @@
-spring-security.version=6.1.0-RC1

+ 0 - 29
samples/device-grant-authorizationserver/samples-device-grant-authorizationserver.gradle

@@ -1,29 +0,0 @@
-plugins {
-	id "org.springframework.boot" version "3.0.0"
-	id "io.spring.dependency-management" version "1.0.11.RELEASE"
-	id "java"
-}
-
-group = project.rootProject.group
-version = project.rootProject.version
-sourceCompatibility = "17"
-
-repositories {
-	mavenCentral()
-	maven { url = "https://repo.spring.io/milestone" }
-}
-
-dependencies {
-	implementation "org.springframework.boot:spring-boot-starter-web"
-	implementation "org.springframework.boot:spring-boot-starter-security"
-	implementation "org.springframework.boot:spring-boot-starter-jdbc"
-	implementation project(":spring-security-oauth2-authorization-server")
-	implementation "org.springframework.boot:spring-boot-starter-thymeleaf"
-	implementation "org.webjars:webjars-locator-core"
-	implementation "org.webjars:bootstrap:3.4.1"
-	implementation "org.webjars:jquery:3.4.1"
-	runtimeOnly "com.h2database:h2"
-
-	testImplementation "org.springframework.boot:spring-boot-starter-test"
-	testImplementation "org.springframework.security:spring-security-test"
-}

+ 0 - 32
samples/device-grant-authorizationserver/src/main/java/sample/DeviceGrantAuthorizationServerApplication.java

@@ -1,32 +0,0 @@
-/*
- * Copyright 2020-2023 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 Steve Riesenberg
- * @since 1.1
- */
-@SpringBootApplication
-public class DeviceGrantAuthorizationServerApplication {
-
-	public static void main(String[] args) {
-		SpringApplication.run(DeviceGrantAuthorizationServerApplication.class, args);
-	}
-
-}

+ 0 - 237
samples/device-grant-authorizationserver/src/main/java/sample/config/SecurityConfig.java

@@ -1,237 +0,0 @@
-/*
- * Copyright 2020-2023 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 java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.util.UUID;
-
-import com.nimbusds.jose.jwk.JWKSet;
-import com.nimbusds.jose.jwk.RSAKey;
-import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
-import com.nimbusds.jose.jwk.source.JWKSource;
-import com.nimbusds.jose.proc.SecurityContext;
-import sample.authentication.DeviceClientAuthenticationProvider;
-import sample.web.authentication.DeviceClientAuthenticationConverter;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.annotation.Order;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
-import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
-import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
-import org.springframework.security.config.Customizer;
-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.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
-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.oauth2.core.AuthorizationGrantType;
-import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
-import org.springframework.security.oauth2.core.oidc.OidcScopes;
-import org.springframework.security.oauth2.jwt.JwtDecoder;
-import org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService;
-import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
-import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
-import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
-import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
-import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
-import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
-import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
-import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
-import org.springframework.security.provisioning.InMemoryUserDetailsManager;
-import org.springframework.security.web.SecurityFilterChain;
-import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
-
-/**
- * @author Steve Riesenberg
- * @since 1.1
- */
-@Configuration(proxyBeanMethods = false)
-@EnableWebSecurity
-public class SecurityConfig {
-
-	@Bean
-	@Order(1)
-	public SecurityFilterChain authorizationServerSecurityFilterChain(
-			HttpSecurity http, RegisteredClientRepository registeredClientRepository,
-			AuthorizationServerSettings authorizationServerSettings) throws Exception {
-		OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
-
-		/*
-		 * This sample demonstrates the use of a public client that does not
-		 * store credentials or authenticate with the authorization server.
-		 *
-		 * The following components show how to customize the authorization
-		 * server to allow for device clients to perform requests to the
-		 * OAuth 2.0 Device Authorization Endpoint and Token Endpoint without
-		 * a clientId/clientSecret.
-		 *
-		 * CAUTION: These endpoints will not require any authentication, and can
-		 * be accessed by any client that has a valid clientId.
-		 *
-		 * It is therefore RECOMMENDED to carefully monitor the use of these
-		 * endpoints and employ any additional protections as needed, which is
-		 * outside the scope of this sample.
-		 */
-		DeviceClientAuthenticationConverter deviceClientAuthenticationConverter =
-				new DeviceClientAuthenticationConverter(
-						authorizationServerSettings.getDeviceAuthorizationEndpoint());
-		DeviceClientAuthenticationProvider deviceClientAuthenticationProvider =
-				new DeviceClientAuthenticationProvider(registeredClientRepository);
-
-		// @formatter:off
-		http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
-			.deviceAuthorizationEndpoint((deviceAuthorizationEndpoint) -> deviceAuthorizationEndpoint
-				.verificationUri("/activate")
-			)
-			.clientAuthentication((clientAuthentication) -> clientAuthentication
-				.authenticationConverter(deviceClientAuthenticationConverter)
-				.authenticationProvider(deviceClientAuthenticationProvider)
-			)
-			.oidc(Customizer.withDefaults());	// Enable OpenID Connect 1.0
-		// @formatter:on
-
-		// @formatter:off
-		http
-			.exceptionHandling((exceptions) -> exceptions
-				.authenticationEntryPoint(
-					new LoginUrlAuthenticationEntryPoint("/login"))
-			)
-			.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
-		// @formatter:on
-
-		return http.build();
-	}
-
-	@Bean
-	@Order(2)
-	public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
-		// @formatter:off
-		http
-			.authorizeHttpRequests((authorize) -> authorize
-				.anyRequest().authenticated()
-			)
-			.formLogin(Customizer.withDefaults());
-		// @formatter:on
-
-		return http.build();
-	}
-
-	@Bean
-	public UserDetailsService userDetailsService() {
-		// @formatter:off
-		UserDetails userDetails = User.withDefaultPasswordEncoder()
-				.username("user1")
-				.password("password")
-				.roles("USER")
-				.build();
-		// @formatter:on
-
-		return new InMemoryUserDetailsManager(userDetails);
-	}
-
-	@Bean
-	public RegisteredClientRepository registeredClientRepository() {
-		RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
-				.clientId("messaging-client")
-				.clientSecret("{noop}secret")
-				.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
-				.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
-				.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
-				.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
-				.redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc")
-				.redirectUri("http://127.0.0.1:8080/authorized")
-				.scope(OidcScopes.OPENID)
-				.scope(OidcScopes.PROFILE)
-				.scope("message.read")
-				.scope("message.write")
-				.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
-				.build();
-
-		RegisteredClient deviceClient = RegisteredClient.withId(UUID.randomUUID().toString())
-				.clientId("device-messaging-client")
-				.clientAuthenticationMethod(ClientAuthenticationMethod.NONE)
-				.authorizationGrantType(AuthorizationGrantType.DEVICE_CODE)
-				.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
-				.scope("message.read")
-				.scope("message.write")
-				.build();
-
-		return new InMemoryRegisteredClientRepository(registeredClient, deviceClient);
-	}
-
-	@Bean
-	public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate,
-			RegisteredClientRepository registeredClientRepository) {
-		return new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository);
-	}
-
-	@Bean
-	public JWKSource<SecurityContext> jwkSource() {
-		KeyPair keyPair = generateRsaKey();
-		RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
-		RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
-		RSAKey rsaKey = new RSAKey.Builder(publicKey)
-				.privateKey(privateKey)
-				.keyID(UUID.randomUUID().toString())
-				.build();
-		JWKSet jwkSet = new JWKSet(rsaKey);
-		return new ImmutableJWKSet<>(jwkSet);
-	}
-
-	private static KeyPair generateRsaKey() {
-		KeyPair keyPair;
-		try {
-			KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
-			keyPairGenerator.initialize(2048);
-			keyPair = keyPairGenerator.generateKeyPair();
-		}
-		catch (Exception ex) {
-			throw new IllegalStateException(ex);
-		}
-		return keyPair;
-	}
-
-	@Bean
-	public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
-		return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
-	}
-
-	@Bean
-	public AuthorizationServerSettings authorizationServerSettings() {
-		return AuthorizationServerSettings.builder().build();
-	}
-
-	@Bean
-	public EmbeddedDatabase embeddedDatabase() {
-		// @formatter:off
-		return new EmbeddedDatabaseBuilder()
-				.generateUniqueName(true)
-				.setType(EmbeddedDatabaseType.H2)
-				.setScriptEncoding("UTF-8")
-				.addScript("org/springframework/security/oauth2/server/authorization/oauth2-authorization-schema.sql")
-				.addScript("org/springframework/security/oauth2/server/authorization/oauth2-authorization-consent-schema.sql")
-				.addScript("org/springframework/security/oauth2/server/authorization/client/oauth2-registered-client-schema.sql")
-				.build();
-		// @formatter:on
-	}
-
-}

+ 0 - 6
samples/device-grant-authorizationserver/src/main/resources/application.yml

@@ -1,6 +0,0 @@
-server:
-  port: 9000
-
-logging:
-  level:
-    org.springframework.security: trace

+ 0 - 0
samples/device-grant-authorizationserver/src/main/java/sample/authentication/DeviceClientAuthenticationProvider.java → samples/featured-authorizationserver/src/main/java/sample/authentication/DeviceClientAuthenticationProvider.java


+ 0 - 0
samples/device-grant-authorizationserver/src/main/java/sample/authentication/DeviceClientAuthenticationToken.java → samples/featured-authorizationserver/src/main/java/sample/authentication/DeviceClientAuthenticationToken.java


+ 53 - 5
samples/featured-authorizationserver/src/main/java/sample/config/AuthorizationServerConfig.java

@@ -21,9 +21,11 @@ import com.nimbusds.jose.jwk.JWKSet;
 import com.nimbusds.jose.jwk.RSAKey;
 import com.nimbusds.jose.jwk.RSAKey;
 import com.nimbusds.jose.jwk.source.JWKSource;
 import com.nimbusds.jose.jwk.source.JWKSource;
 import com.nimbusds.jose.proc.SecurityContext;
 import com.nimbusds.jose.proc.SecurityContext;
+import sample.authentication.DeviceClientAuthenticationProvider;
 import sample.jose.Jwks;
 import sample.jose.Jwks;
 import sample.security.FederatedIdentityConfigurer;
 import sample.security.FederatedIdentityConfigurer;
 import sample.security.FederatedIdentityIdTokenCustomizer;
 import sample.security.FederatedIdentityIdTokenCustomizer;
+import sample.web.authentication.DeviceClientAuthenticationConverter;
 
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Configuration;
@@ -67,12 +69,48 @@ public class AuthorizationServerConfig {
 
 
 	@Bean
 	@Bean
 	@Order(Ordered.HIGHEST_PRECEDENCE)
 	@Order(Ordered.HIGHEST_PRECEDENCE)
-	public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
+	public SecurityFilterChain authorizationServerSecurityFilterChain(
+			HttpSecurity http, RegisteredClientRepository registeredClientRepository,
+			AuthorizationServerSettings authorizationServerSettings) throws Exception {
+
 		OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
 		OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
+
+		/*
+		 * This sample demonstrates the use of a public client that does not
+		 * store credentials or authenticate with the authorization server.
+		 *
+		 * The following components show how to customize the authorization
+		 * server to allow for device clients to perform requests to the
+		 * OAuth 2.0 Device Authorization Endpoint and Token Endpoint without
+		 * a clientId/clientSecret.
+		 *
+		 * CAUTION: These endpoints will not require any authentication, and can
+		 * be accessed by any client that has a valid clientId.
+		 *
+		 * It is therefore RECOMMENDED to carefully monitor the use of these
+		 * endpoints and employ any additional protections as needed, which is
+		 * outside the scope of this sample.
+		 */
+		DeviceClientAuthenticationConverter deviceClientAuthenticationConverter =
+				new DeviceClientAuthenticationConverter(
+						authorizationServerSettings.getDeviceAuthorizationEndpoint());
+		DeviceClientAuthenticationProvider deviceClientAuthenticationProvider =
+				new DeviceClientAuthenticationProvider(registeredClientRepository);
+
+		// @formatter:off
 		http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
 		http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
-				.authorizationEndpoint(authorizationEndpoint ->
-						authorizationEndpoint.consentPage(CUSTOM_CONSENT_PAGE_URI))
-				.oidc(Customizer.withDefaults());	// Enable OpenID Connect 1.0
+			.deviceAuthorizationEndpoint(deviceAuthorizationEndpoint ->
+				deviceAuthorizationEndpoint.verificationUri("/activate")
+			)
+			.clientAuthentication(clientAuthentication ->
+				clientAuthentication
+					.authenticationConverter(deviceClientAuthenticationConverter)
+					.authenticationProvider(deviceClientAuthenticationProvider)
+			)
+			.authorizationEndpoint(authorizationEndpoint ->
+				authorizationEndpoint.consentPage(CUSTOM_CONSENT_PAGE_URI))
+			.oidc(Customizer.withDefaults());	// Enable OpenID Connect 1.0
+		// @formatter:on
 
 
 		// @formatter:off
 		// @formatter:off
 		http
 		http
@@ -106,9 +144,19 @@ public class AuthorizationServerConfig {
 				.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
 				.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
 				.build();
 				.build();
 
 
-		// Save registered client in db as if in-memory
+		RegisteredClient deviceClient = RegisteredClient.withId(UUID.randomUUID().toString())
+				.clientId("device-messaging-client")
+				.clientAuthenticationMethod(ClientAuthenticationMethod.NONE)
+				.authorizationGrantType(AuthorizationGrantType.DEVICE_CODE)
+				.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
+				.scope("message.read")
+				.scope("message.write")
+				.build();
+
+		// Save registered client's in db as if in-memory
 		JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository(jdbcTemplate);
 		JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository(jdbcTemplate);
 		registeredClientRepository.save(registeredClient);
 		registeredClientRepository.save(registeredClient);
+		registeredClientRepository.save(deviceClient);
 
 
 		return registeredClientRepository;
 		return registeredClientRepository;
 	}
 	}

+ 1 - 1
samples/device-grant-authorizationserver/src/main/java/sample/web/DeviceController.java → samples/featured-authorizationserver/src/main/java/sample/web/DeviceController.java

@@ -13,7 +13,6 @@
  * See the License for the specific language governing permissions and
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * limitations under the License.
  */
  */
-
 package sample.web;
 package sample.web;
 
 
 import org.springframework.stereotype.Controller;
 import org.springframework.stereotype.Controller;
@@ -22,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestParam;
 
 
 /**
 /**
  * @author Steve Riesenberg
  * @author Steve Riesenberg
+ * @since 1.1
  */
  */
 @Controller
 @Controller
 public class DeviceController {
 public class DeviceController {

+ 0 - 0
samples/device-grant-authorizationserver/src/main/java/sample/web/DeviceErrorController.java → samples/featured-authorizationserver/src/main/java/sample/web/DeviceErrorController.java


+ 1 - 0
samples/device-grant-authorizationserver/src/main/java/sample/web/authentication/DeviceClientAuthenticationConverter.java → samples/featured-authorizationserver/src/main/java/sample/web/authentication/DeviceClientAuthenticationConverter.java

@@ -16,6 +16,7 @@
 package sample.web.authentication;
 package sample.web.authentication;
 
 
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletRequest;
+
 import sample.authentication.DeviceClientAuthenticationToken;
 import sample.authentication.DeviceClientAuthenticationToken;
 
 
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpMethod;

+ 0 - 0
samples/device-grant-authorizationserver/src/main/resources/static/assets/css/style.css → samples/featured-authorizationserver/src/main/resources/static/assets/css/style.css


+ 0 - 0
samples/device-grant-authorizationserver/src/main/resources/templates/access-denied.html → samples/featured-authorizationserver/src/main/resources/templates/access-denied.html


+ 0 - 0
samples/device-grant-authorizationserver/src/main/resources/templates/activate.html → samples/featured-authorizationserver/src/main/resources/templates/activate.html


+ 0 - 0
samples/device-grant-authorizationserver/src/main/resources/templates/activated.html → samples/featured-authorizationserver/src/main/resources/templates/activated.html


+ 0 - 0
samples/device-grant-authorizationserver/src/main/resources/templates/error.html → samples/featured-authorizationserver/src/main/resources/templates/error.html