Add security on endpoints and handle 403 responses.

This commit is contained in:
Florian THIERRY
2023-11-30 14:56:03 +01:00
parent 96345c703a
commit 920fbe489d
7 changed files with 60 additions and 23 deletions

View File

@@ -1,9 +1,13 @@
package org.sportshub.application.configuration;
import static org.sportshub.domain.user.model.UserRole.ADMIN;
import static org.springframework.http.HttpMethod.GET;
import static org.springframework.http.HttpMethod.OPTIONS;
import static org.springframework.http.HttpMethod.POST;
import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS;
import org.sportshub.application.security.JwtAuthenticationFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@@ -12,7 +16,6 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import static jakarta.servlet.DispatcherType.FORWARD;
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
@@ -29,27 +32,29 @@ public class SecurityConfiguration {
httpSecurity
.csrf(AbstractHttpConfigurer::disable)
.httpBasic(Customizer.withDefaults())
.exceptionHandling(configurer -> configurer
.authenticationEntryPoint((request, response, authException) -> response.sendError(SC_UNAUTHORIZED))
.accessDeniedHandler((request, response, accessDeniedException) -> response.sendError(SC_FORBIDDEN))
)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.sessionManagement(customizer -> customizer.sessionCreationPolicy(STATELESS))
.authorizeHttpRequests(requests -> requests
.dispatcherTypeMatchers(FORWARD).permitAll()
.requestMatchers(
HttpMethod.GET,
"/api/health/check"
GET,
"/api/health/check",
"/error"
).permitAll()
.requestMatchers(
HttpMethod.POST,
GET,
"/api/users"
).hasAuthority(ADMIN.name())
.requestMatchers(
POST,
"/api/users/login"
).permitAll()
.requestMatchers(OPTIONS).permitAll()
.anyRequest().authenticated()
)
.exceptionHandling(configurer -> configurer
.defaultAuthenticationEntryPointFor(
(request, response, authException) -> response.sendError(SC_UNAUTHORIZED),
new AntPathRequestMatcher("/api/**")
).defaultAccessDeniedHandlerFor(
(request, response, accessDeniedException) -> response.sendError(SC_FORBIDDEN),
new AntPathRequestMatcher("/api/**")
)
);
return httpSecurity.build();

View File

@@ -1,10 +1,11 @@
package org.sportshub.application.security.model;
import static java.util.Collections.emptyList;
import java.util.Collection;
import org.sportshub.domain.user.model.User;
import org.sportshub.domain.user.model.UserRole;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
public class CustomUserDetails implements UserDetails {
@@ -16,7 +17,12 @@ public class CustomUserDetails implements UserDetails {
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return emptyList();
return user.roles()
.stream()
.map(UserRole::name)
.map(role -> "ROLE_" + role)
.map(SimpleGrantedAuthority::new)
.toList();
}
@Override

View File

@@ -1,8 +1,10 @@
package org.sportshub.domain.user.model;
import java.util.List;
import java.util.UUID;
public record User(
UUID id,
String password
String password,
List<UserRole> roles
) {}

View File

@@ -0,0 +1,6 @@
package org.sportshub.domain.user.model;
public enum UserRole {
STANDARD,
ADMIN
}

View File

@@ -1,12 +1,10 @@
package org.sportshub.exposition.user;
import java.util.List;
import java.util.Optional;
import org.sportshub.application.user.UserUseCases;
import org.sportshub.domain.user.model.User;
import org.sportshub.exposition.user.model.LoginRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

View File

@@ -4,6 +4,8 @@ import java.util.List;
import java.util.Optional;
import java.util.UUID;
import static org.sportshub.domain.user.model.UserRole.ADMIN;
import static org.sportshub.domain.user.model.UserRole.STANDARD;
import org.sportshub.domain.user.model.User;
import org.sportshub.domain.user.port.UserPort;
import org.springframework.stereotype.Component;
@@ -11,9 +13,21 @@ import org.springframework.stereotype.Component;
@Component
public class UserInMemoryAdapter implements UserPort {
private static final List<User> users = List.of(
new User(UUID.fromString("c1a0805f-c618-47dc-bae7-bee70503644e"), "$2a$10$WPuLOKpvaQnMotNo5ijPwegBPwmMF1C04XkTNCBpeBFo4r2YJWy.2"),
new User(UUID.fromString("4eff194d-dd8e-463e-974f-034bfd509f84"), "$2a$10$WPuLOKpvaQnMotNo5ijPwegBPwmMF1C04XkTNCBpeBFo4r2YJWy.2"),
new User(UUID.fromString("c78d7d7c-0386-415d-86dc-98a470591e07"), "$2a$10$WPuLOKpvaQnMotNo5ijPwegBPwmMF1C04XkTNCBpeBFo4r2YJWy.2")
new User(
UUID.fromString("c1a0805f-c618-47dc-bae7-bee70503644e"),
"$2a$10$WPuLOKpvaQnMotNo5ijPwegBPwmMF1C04XkTNCBpeBFo4r2YJWy.2",
List.of(STANDARD)
),
new User(
UUID.fromString("4eff194d-dd8e-463e-974f-034bfd509f84"),
"$2a$10$WPuLOKpvaQnMotNo5ijPwegBPwmMF1C04XkTNCBpeBFo4r2YJWy.2",
List.of(STANDARD)
),
new User(
UUID.fromString("c78d7d7c-0386-415d-86dc-98a470591e07"),
"$2a$10$WPuLOKpvaQnMotNo5ijPwegBPwmMF1C04XkTNCBpeBFo4r2YJWy.2",
List.of(STANDARD, ADMIN)
)
);
@Override

View File

@@ -6,3 +6,9 @@ application:
logging:
level:
org.springframework.security: DEBUG
server:
error:
whitelabel:
enabled: false # Disable html error responses.
include-stacktrace: never