diff --git a/src/main/java/com/alibou/security/config/CustomAccessDeniedHandler.java b/src/main/java/com/alibou/security/config/CustomAccessDeniedHandler.java new file mode 100644 index 0000000..3495149 --- /dev/null +++ b/src/main/java/com/alibou/security/config/CustomAccessDeniedHandler.java @@ -0,0 +1,32 @@ +package com.alibou.security.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.stereotype.Component; + +import java.io.OutputStream; + +@Component +@RequiredArgsConstructor +public class CustomAccessDeniedHandler implements AccessDeniedHandler { + + private final ObjectMapper objectMapper; + + @Override + @SneakyThrows + public void handle(HttpServletRequest request, HttpServletResponse response, org.springframework.security.access.AccessDeniedException accessDeniedException){ + response.setContentType("application/json"); + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + + OutputStream out = response.getOutputStream(); + objectMapper.writeValue(out, ResponseEntity.status(HttpStatus.FORBIDDEN).body("Access denied")); + out.flush(); + out.close(); + } +} diff --git a/src/main/java/com/alibou/security/config/CustomAuthenticationEntryPoint.java b/src/main/java/com/alibou/security/config/CustomAuthenticationEntryPoint.java new file mode 100644 index 0000000..cf2a28d --- /dev/null +++ b/src/main/java/com/alibou/security/config/CustomAuthenticationEntryPoint.java @@ -0,0 +1,33 @@ +package com.alibou.security.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import java.io.OutputStream; + +@Component +@RequiredArgsConstructor +public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { + + private final ObjectMapper mapper; + + @Override + @SneakyThrows + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException){ + response.setContentType("application/json"); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + + OutputStream out = response.getOutputStream(); + mapper.writeValue(out, ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Unauthorized")); + out.flush(); + out.close(); + } +} diff --git a/src/main/java/com/alibou/security/config/SecurityConfiguration.java b/src/main/java/com/alibou/security/config/SecurityConfiguration.java index e4aefe6..c78f86b 100644 --- a/src/main/java/com/alibou/security/config/SecurityConfiguration.java +++ b/src/main/java/com/alibou/security/config/SecurityConfiguration.java @@ -13,20 +13,10 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.logout.LogoutHandler; -import static com.alibou.security.user.Permission.ADMIN_CREATE; -import static com.alibou.security.user.Permission.ADMIN_DELETE; -import static com.alibou.security.user.Permission.ADMIN_READ; -import static com.alibou.security.user.Permission.ADMIN_UPDATE; -import static com.alibou.security.user.Permission.MANAGER_CREATE; -import static com.alibou.security.user.Permission.MANAGER_DELETE; -import static com.alibou.security.user.Permission.MANAGER_READ; -import static com.alibou.security.user.Permission.MANAGER_UPDATE; +import static com.alibou.security.user.Permission.*; import static com.alibou.security.user.Role.ADMIN; import static com.alibou.security.user.Role.MANAGER; -import static org.springframework.http.HttpMethod.DELETE; -import static org.springframework.http.HttpMethod.GET; -import static org.springframework.http.HttpMethod.POST; -import static org.springframework.http.HttpMethod.PUT; +import static org.springframework.http.HttpMethod.*; import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS; @Configuration @@ -45,10 +35,15 @@ public class SecurityConfiguration { "/configuration/security", "/swagger-ui/**", "/webjars/**", - "/swagger-ui.html"}; + "/swagger-ui.html", + "/swagger-ui/**", + "/api-docs/**", + "/"}; private final JwtAuthenticationFilter jwtAuthFilter; private final AuthenticationProvider authenticationProvider; private final LogoutHandler logoutHandler; + private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint; + private final CustomAccessDeniedHandler customAccessDeniedHandler; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { @@ -73,7 +68,9 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .addLogoutHandler(logoutHandler) .logoutSuccessHandler((request, response, authentication) -> SecurityContextHolder.clearContext()) ) - ; + .exceptionHandling(exception-> exception + .authenticationEntryPoint(customAuthenticationEntryPoint) + .accessDeniedHandler(customAccessDeniedHandler)); return http.build(); } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 71b71d1..baf455a 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -21,3 +21,10 @@ application: expiration: 86400000 # a day refresh-token: expiration: 604800000 # 7 days + +springdoc: + swagger-ui: + path: / + api-docs: + path: /api-docs +