123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- /*
- * Copyright 2020-2024 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.userinfo;
- 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 org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.core.annotation.Order;
- import org.springframework.http.MediaType;
- 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.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.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;
- import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
- @Configuration(proxyBeanMethods = false)
- @EnableWebSecurity
- public class EnableUserInfoSecurityConfig {
- @Bean // <1>
- @Order(1)
- public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
- OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
- OAuth2AuthorizationServerConfigurer.authorizationServer();
- // @formatter:off
- http
- .securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
- .with(authorizationServerConfigurer, (authorizationServer) ->
- authorizationServer
- .oidc(Customizer.withDefaults()) // <2>
- )
- .authorizeHttpRequests((authorize) ->
- authorize
- .anyRequest().authenticated()
- )
- .exceptionHandling((exceptions) -> exceptions
- .defaultAuthenticationEntryPointFor(
- new LoginUrlAuthenticationEntryPoint("/login"),
- new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
- )
- );
- // @formatter:on
- return http.build();
- }
- // @fold:on
- @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();
- }
- // @fold:off
- @Bean // <3>
- public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
- return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
- }
- // @fold:on
- @Bean
- public UserDetailsService userDetailsService() {
- // @formatter:off
- UserDetails userDetails = User.withDefaultPasswordEncoder()
- .username("user")
- .password("password")
- .roles("USER")
- .build();
- // @formatter:on
- return new InMemoryUserDetailsManager(userDetails);
- }
- @Bean
- public RegisteredClientRepository registeredClientRepository() {
- // @formatter:off
- 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.ADDRESS)
- .scope(OidcScopes.EMAIL)
- .scope(OidcScopes.PHONE)
- .scope(OidcScopes.PROFILE)
- .scope("message.read")
- .scope("message.write")
- .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
- .build();
- // @formatter:on
- return new InMemoryRegisteredClientRepository(registeredClient);
- }
- @Bean
- public JWKSource<SecurityContext> jwkSource() {
- KeyPair keyPair = generateRsaKey();
- RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
- RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
- // @formatter:off
- RSAKey rsaKey = new RSAKey.Builder(publicKey)
- .privateKey(privateKey)
- .keyID(UUID.randomUUID().toString())
- .build();
- // @formatter:on
- 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 AuthorizationServerSettings authorizationServerSettings() {
- return AuthorizationServerSettings.builder().build();
- }
- // @fold:off
- }
|