SecurityConfig.java 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * Copyright 2020-2023 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * https://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package sample.config;
  17. import java.security.KeyPair;
  18. import java.security.KeyPairGenerator;
  19. import java.security.interfaces.RSAPrivateKey;
  20. import java.security.interfaces.RSAPublicKey;
  21. import java.util.UUID;
  22. import com.nimbusds.jose.jwk.JWKSet;
  23. import com.nimbusds.jose.jwk.RSAKey;
  24. import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
  25. import com.nimbusds.jose.jwk.source.JWKSource;
  26. import com.nimbusds.jose.proc.SecurityContext;
  27. import org.springframework.context.annotation.Bean;
  28. import org.springframework.context.annotation.Configuration;
  29. import org.springframework.core.annotation.Order;
  30. import org.springframework.security.config.Customizer;
  31. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  32. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  33. import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
  34. import org.springframework.security.core.userdetails.User;
  35. import org.springframework.security.core.userdetails.UserDetails;
  36. import org.springframework.security.core.userdetails.UserDetailsService;
  37. import org.springframework.security.oauth2.core.AuthorizationGrantType;
  38. import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
  39. import org.springframework.security.oauth2.core.oidc.OidcScopes;
  40. import org.springframework.security.oauth2.jwt.JwtDecoder;
  41. import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
  42. import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
  43. import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
  44. import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
  45. import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
  46. import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
  47. import org.springframework.security.oauth2.server.authorization.settings.ClientSettings;
  48. import org.springframework.security.provisioning.InMemoryUserDetailsManager;
  49. import org.springframework.security.web.SecurityFilterChain;
  50. import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
  51. /**
  52. * @author Steve Riesenberg
  53. * @since 1.1
  54. */
  55. @Configuration(proxyBeanMethods = false)
  56. @EnableWebSecurity
  57. public class SecurityConfig {
  58. @Bean
  59. @Order(1)
  60. public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
  61. OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
  62. http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
  63. .deviceAuthorizationEndpoint((deviceAuthorizationEndpoint) -> deviceAuthorizationEndpoint
  64. .verificationUri("/activate")
  65. )
  66. .oidc(Customizer.withDefaults()); // Enable OpenID Connect 1.0
  67. // @formatter:off
  68. http
  69. .exceptionHandling((exceptions) -> exceptions
  70. .authenticationEntryPoint(
  71. new LoginUrlAuthenticationEntryPoint("/login"))
  72. )
  73. .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
  74. // @formatter:on
  75. return http.build();
  76. }
  77. @Bean
  78. @Order(2)
  79. public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
  80. // @formatter:off
  81. http
  82. .authorizeHttpRequests((authorize) -> authorize
  83. .anyRequest().authenticated()
  84. )
  85. .formLogin(Customizer.withDefaults());
  86. // @formatter:on
  87. return http.build();
  88. }
  89. @Bean
  90. public UserDetailsService userDetailsService() {
  91. // @formatter:off
  92. UserDetails userDetails = User.withDefaultPasswordEncoder()
  93. .username("user1")
  94. .password("password")
  95. .roles("USER")
  96. .build();
  97. // @formatter:on
  98. return new InMemoryUserDetailsManager(userDetails);
  99. }
  100. @Bean
  101. public RegisteredClientRepository registeredClientRepository() {
  102. RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
  103. .clientId("messaging-client")
  104. .clientSecret("{noop}secret")
  105. .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
  106. .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
  107. .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
  108. .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
  109. .authorizationGrantType(AuthorizationGrantType.DEVICE_CODE)
  110. .redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc")
  111. .redirectUri("http://127.0.0.1:8080/authorized")
  112. .scope(OidcScopes.OPENID)
  113. .scope(OidcScopes.PROFILE)
  114. .scope("message.read")
  115. .scope("message.write")
  116. .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
  117. .build();
  118. return new InMemoryRegisteredClientRepository(registeredClient);
  119. }
  120. @Bean
  121. public JWKSource<SecurityContext> jwkSource() {
  122. KeyPair keyPair = generateRsaKey();
  123. RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  124. RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
  125. RSAKey rsaKey = new RSAKey.Builder(publicKey)
  126. .privateKey(privateKey)
  127. .keyID(UUID.randomUUID().toString())
  128. .build();
  129. JWKSet jwkSet = new JWKSet(rsaKey);
  130. return new ImmutableJWKSet<>(jwkSet);
  131. }
  132. private static KeyPair generateRsaKey() {
  133. KeyPair keyPair;
  134. try {
  135. KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
  136. keyPairGenerator.initialize(2048);
  137. keyPair = keyPairGenerator.generateKeyPair();
  138. }
  139. catch (Exception ex) {
  140. throw new IllegalStateException(ex);
  141. }
  142. return keyPair;
  143. }
  144. @Bean
  145. public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
  146. return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
  147. }
  148. @Bean
  149. public AuthorizationServerSettings authorizationServerSettings() {
  150. return AuthorizationServerSettings.builder().build();
  151. }
  152. }