Partially implement resource server tweak some settings
This commit is contained in:
@ -0,0 +1,25 @@
|
||||
package com.backend.user.service.anyame.component;
|
||||
|
||||
import com.backend.user.service.anyame.service.UserAuthorityService;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthentication;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class CustomOpaqueTokenAuthenticationConverter implements OpaqueTokenAuthenticationConverter {
|
||||
private final OpaqueTokenIntrospector introspector;
|
||||
private final UserAuthorityService authorityService;
|
||||
|
||||
public CustomOpaqueTokenAuthenticationConverter(OpaqueTokenIntrospector introspector, UserAuthorityService authorityService) {
|
||||
this.introspector = introspector;
|
||||
this.authorityService = authorityService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication convert(String introspectedToken, OAuth2AuthenticatedPrincipal authenticatedPrincipal) {
|
||||
return new BearerTokenAuthentication(authenticatedPrincipal, introspectedToken, authenticatedPrincipal.getAuthorities());
|
||||
}
|
||||
}
|
@ -1,23 +1,18 @@
|
||||
package com.backend.user.service.anyame.config;
|
||||
|
||||
import com.backend.user.service.anyame.component.AuthorizationServerProperties;
|
||||
import com.nimbusds.jose.jwk.source.JWKSource;
|
||||
import com.nimbusds.jose.proc.SecurityContext;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import com.backend.user.service.anyame.component.CustomOpaqueTokenAuthenticationConverter;
|
||||
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.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;
|
||||
@ -26,36 +21,48 @@ import org.springframework.security.oauth2.server.authorization.settings.TokenSe
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.springframework.security.config.Customizer.withDefaults;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class AuthorizationServerConfig {
|
||||
private final AuthorizationServerProperties authorizationServerProperties;
|
||||
private final CustomOpaqueTokenAuthenticationConverter opaqueTokenAuthenticationConverter;
|
||||
|
||||
public AuthorizationServerConfig(AuthorizationServerProperties authorizationServerProperties) {
|
||||
public AuthorizationServerConfig(AuthorizationServerProperties authorizationServerProperties, CustomOpaqueTokenAuthenticationConverter opaqueTokenAuthenticationConverter) {
|
||||
this.authorizationServerProperties = authorizationServerProperties;
|
||||
this.opaqueTokenAuthenticationConverter = opaqueTokenAuthenticationConverter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(1)
|
||||
public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http, @Qualifier("corsConfigurationSource") CorsConfigurationSource configurationSource) throws Exception {
|
||||
public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception {
|
||||
OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
|
||||
OAuth2AuthorizationServerConfigurer.authorizationServer();
|
||||
|
||||
RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();
|
||||
|
||||
return http
|
||||
.cors(c -> c.configurationSource(configurationSource))
|
||||
.securityMatcher(authorizationServerConfigurer.getEndpointsMatcher())
|
||||
.csrf(c -> c.ignoringRequestMatchers(endpointsMatcher))
|
||||
.securityMatcher(endpointsMatcher)
|
||||
.with(authorizationServerConfigurer, (authorizationServer) ->
|
||||
authorizationServer
|
||||
.oidc(Customizer.withDefaults())
|
||||
.oidc(withDefaults())
|
||||
)
|
||||
.authorizeHttpRequests((authorize) ->
|
||||
authorize
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.oauth2ResourceServer(c -> c
|
||||
.opaqueToken(opaqueTokenConfigurer -> opaqueTokenConfigurer
|
||||
.authenticationConverter(opaqueTokenAuthenticationConverter)
|
||||
)
|
||||
)
|
||||
.exceptionHandling((exceptions) -> exceptions
|
||||
.defaultAuthenticationEntryPointFor(
|
||||
new LoginUrlAuthenticationEntryPoint("/login"),
|
||||
@ -69,7 +76,7 @@ public class AuthorizationServerConfig {
|
||||
public RegisteredClientRepository registeredClientRepository() {
|
||||
RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString())
|
||||
.clientId("oidc-client")
|
||||
.clientSecret("{noop}secret")
|
||||
.clientSecret("$2a$12$IdGgEQv2Zmtx.dEHvUhxJ.Pi3x9lufrvcfkQ8e4t2pwhD7F8swEJu")
|
||||
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
|
||||
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
|
||||
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
|
||||
@ -90,10 +97,6 @@ public class AuthorizationServerConfig {
|
||||
return new InMemoryRegisteredClientRepository(oidcClient);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
|
||||
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AuthorizationServerSettings authorizationServerSettings() {
|
||||
|
@ -0,0 +1,14 @@
|
||||
package com.backend.user.service.anyame.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.oauth2.server.authorization.InMemoryOAuth2AuthorizationService;
|
||||
import org.springframework.security.oauth2.server.authorization.OAuth2AuthorizationService;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
public class ConfigUtilities {
|
||||
@Bean
|
||||
public OAuth2AuthorizationService oAuth2AuthorizationService() {
|
||||
return new InMemoryOAuth2AuthorizationService();
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ package com.backend.user.service.anyame.config;
|
||||
|
||||
import com.backend.user.service.anyame.service.CustomOAuth2UserService;
|
||||
import com.backend.user.service.anyame.service.CustomUserDetailsService;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
@ -12,7 +11,6 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
|
||||
import static org.springframework.security.config.Customizer.withDefaults;
|
||||
|
||||
@ -32,9 +30,8 @@ public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
@Order(2)
|
||||
public SecurityFilterChain filterChain(HttpSecurity http, @Qualifier("corsConfigurationSource") CorsConfigurationSource configurationSource) throws Exception {
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
return http
|
||||
.cors(c -> c.configurationSource(configurationSource))
|
||||
.authorizeHttpRequests(c ->
|
||||
c.anyRequest().authenticated()
|
||||
)
|
||||
|
@ -1,38 +1,31 @@
|
||||
package com.backend.user.service.anyame.config;
|
||||
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOrigins("http://localhost:5173")
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||
.allowedHeaders("*")
|
||||
.allowCredentials(true);
|
||||
}
|
||||
|
||||
@Bean(name = "corsConfigurationSource")
|
||||
public CorsConfigurationSource corsConfigurationSource() {
|
||||
@Bean
|
||||
public FilterRegistrationBean<CorsFilter> corsFilter() {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.setAllowedOrigins(List.of("http://localhost:5173"));
|
||||
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
|
||||
config.setAllowedHeaders(List.of("*"));
|
||||
|
||||
config.setAllowCredentials(true);
|
||||
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
config.addAllowedOrigin("http://127.0.0.1:5173,http://localhost:5173");
|
||||
config.addAllowedHeader(CorsConfiguration.ALL);
|
||||
config.addExposedHeader(CorsConfiguration.ALL);
|
||||
config.addAllowedMethod(CorsConfiguration.ALL);
|
||||
|
||||
source.registerCorsConfiguration("/**", config);
|
||||
return source;
|
||||
FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
|
||||
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
||||
return bean;
|
||||
}
|
||||
}
|
@ -16,4 +16,6 @@ public interface UserRepository extends JpaRepository<User, Long> {
|
||||
"LEFT JOIN FETCH u.roles " +
|
||||
"WHERE u.name = :name")
|
||||
Optional<User> findByNameWithRoles(@Param("name") String name);
|
||||
|
||||
Optional<User> findByProviderId(String name);
|
||||
}
|
@ -70,7 +70,8 @@ public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequ
|
||||
registrationId, email, name, providerId);
|
||||
|
||||
|
||||
User user = userRepository.findByName(name)
|
||||
// TODO: Handle user name conflict
|
||||
User user = userRepository.findByProviderId(providerId)
|
||||
.orElseGet(() -> createNewUser(email, name, registrationId, providerId));
|
||||
|
||||
// TODO: Should be toggleable nor documented behaviour
|
||||
|
@ -72,7 +72,8 @@ public class CustomOIDCUserService extends OidcUserService {
|
||||
log.info("OIDC User - Provider: {}, Email: {}, Name: {}, Subject: {}",
|
||||
registrationId, email, name, subject);
|
||||
|
||||
User user = userRepository.findByName(name)
|
||||
// TODO: Handle user name conflict
|
||||
User user = userRepository.findByProviderId(subject)
|
||||
.orElseGet(() -> createNewUser(email, name, registrationId, subject, picture, preferredUsername));
|
||||
|
||||
// TODO: Should be toggleable nor documented behaviour
|
||||
|
Reference in New Issue
Block a user