From c61958816ba2909c471a991f525656da62ced77f Mon Sep 17 00:00:00 2001 From: Vitor Hideyoshi Nakazone Batista Date: Fri, 16 Feb 2024 03:08:31 -0300 Subject: [PATCH] Fixes Auth Filter for Health Checker --- .../base/security/config/SecurityConfig.java | 1 + .../filter/CustomAuthorizationFilter.java | 54 +++++++++++-------- .../UserResourceAccessInterceptor.java | 3 +- .../api/HealthCheckerController.java | 5 ++ 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/hideyoshi/backendportfolio/base/security/config/SecurityConfig.java b/src/main/java/com/hideyoshi/backendportfolio/base/security/config/SecurityConfig.java index 6167780..2e8cfbd 100644 --- a/src/main/java/com/hideyoshi/backendportfolio/base/security/config/SecurityConfig.java +++ b/src/main/java/com/hideyoshi/backendportfolio/base/security/config/SecurityConfig.java @@ -67,6 +67,7 @@ private void addSecurityToHttp(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/session/**").permitAll() + .and().authorizeRequests().antMatchers("/health").permitAll() .and().authorizeRequests().antMatchers("/user/signup").permitAll() .and().authorizeRequests().antMatchers("/user/oauth/**").permitAll() .and().authorizeRequests().antMatchers("/user/login/**").permitAll() diff --git a/src/main/java/com/hideyoshi/backendportfolio/base/security/filter/CustomAuthorizationFilter.java b/src/main/java/com/hideyoshi/backendportfolio/base/security/filter/CustomAuthorizationFilter.java index b658dcc..87607eb 100644 --- a/src/main/java/com/hideyoshi/backendportfolio/base/security/filter/CustomAuthorizationFilter.java +++ b/src/main/java/com/hideyoshi/backendportfolio/base/security/filter/CustomAuthorizationFilter.java @@ -2,6 +2,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.hideyoshi.backendportfolio.base.security.service.AuthService; +import com.hideyoshi.backendportfolio.util.exception.AuthenticationInvalidException; +import com.hideyoshi.backendportfolio.util.exception.AuthenticationInvalidExceptionDetails; +import com.hideyoshi.backendportfolio.util.exception.BadRequestException; +import org.springframework.http.HttpStatus; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.filter.OncePerRequestFilter; @@ -11,6 +15,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.time.LocalDateTime; import java.util.*; import static org.springframework.http.HttpHeaders.AUTHORIZATION; @@ -20,9 +25,12 @@ public class CustomAuthorizationFilter extends OncePerRequestFilter { private static final List notProtectedPaths = Arrays.asList( + "/health", "/user/login", "/user/signup", - "/user/login/refresh" + "/user/login/refresh", + "/session/validate", + "/session/destroy" ); private static final String AUTHORIZATION_TYPE_STRING = "Bearer "; @@ -38,32 +46,29 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse throws ServletException, IOException { if (this.isPathNotProtected(request.getServletPath())) { filterChain.doFilter(request, response); - } else { - String authorizationHeader = request.getHeader(AUTHORIZATION); - if (Objects.nonNull(authorizationHeader) && authorizationHeader.startsWith(AUTHORIZATION_TYPE_STRING)) { - try { + return; + } - UsernamePasswordAuthenticationToken authenticationToken = - this.authService.verifyAccessToken(authorizationHeader); + String authorizationHeader = request.getHeader(AUTHORIZATION); - SecurityContextHolder.getContext().setAuthentication(authenticationToken); - filterChain.doFilter(request, response); + try { + UsernamePasswordAuthenticationToken authenticationToken = + this.validateUserAccess(authorizationHeader); - } catch (Exception e) { - response.setHeader("error", e.getMessage()); + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + filterChain.doFilter(request, response); - response.setStatus(FORBIDDEN.value()); + } catch (Exception e) { + response.setHeader("error", e.getMessage()); + response.setStatus(FORBIDDEN.value()); - Map error = new HashMap<>(); - error.put("error_message", e.getMessage()); + AuthenticationInvalidExceptionDetails error = new AuthenticationInvalidExceptionDetails("Authentication Failed. Check your credentials.", + HttpStatus.FORBIDDEN.value(), e.getMessage(), + e.getClass().getName(), LocalDateTime.now()); - response.setContentType(APPLICATION_JSON_VALUE); - new ObjectMapper() - .writeValue(response.getOutputStream(), error); - } - } else { - filterChain.doFilter(request, response); - } + response.setContentType(APPLICATION_JSON_VALUE); + new ObjectMapper() + .writeValue(response.getOutputStream(), error); } } @@ -71,4 +76,11 @@ private Boolean isPathNotProtected(String path) { return notProtectedPaths.contains(path); } + private UsernamePasswordAuthenticationToken validateUserAccess(String authorizationHeader) { + if (Objects.nonNull(authorizationHeader) && authorizationHeader.startsWith(AUTHORIZATION_TYPE_STRING)) { + return this.authService.verifyAccessToken(authorizationHeader); + } else { + throw new AuthenticationInvalidException("Access denied"); + } + } } diff --git a/src/main/java/com/hideyoshi/backendportfolio/base/security/interceptor/UserResourceAccessInterceptor.java b/src/main/java/com/hideyoshi/backendportfolio/base/security/interceptor/UserResourceAccessInterceptor.java index 00dfde7..c02f5dc 100644 --- a/src/main/java/com/hideyoshi/backendportfolio/base/security/interceptor/UserResourceAccessInterceptor.java +++ b/src/main/java/com/hideyoshi/backendportfolio/base/security/interceptor/UserResourceAccessInterceptor.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.hideyoshi.backendportfolio.base.user.service.UserService; +import com.hideyoshi.backendportfolio.util.exception.AuthenticationInvalidException; import com.hideyoshi.backendportfolio.util.exception.BadRequestException; import com.hideyoshi.backendportfolio.util.guard.UserResourceGuard; import lombok.RequiredArgsConstructor; @@ -36,7 +37,7 @@ public boolean preHandle(final HttpServletRequest request, final HttpServletResp Boolean accessPermission = annotation.accessType().hasAccess(this.userService, this.objectMapper, request); if (!accessPermission) { - throw new BadRequestException(annotation.denialMessage()); + throw new AuthenticationInvalidException(annotation.denialMessage()); } } return true; diff --git a/src/main/java/com/hideyoshi/backendportfolio/healthChecker/api/HealthCheckerController.java b/src/main/java/com/hideyoshi/backendportfolio/healthChecker/api/HealthCheckerController.java index 938e765..b24ed1e 100644 --- a/src/main/java/com/hideyoshi/backendportfolio/healthChecker/api/HealthCheckerController.java +++ b/src/main/java/com/hideyoshi/backendportfolio/healthChecker/api/HealthCheckerController.java @@ -1,6 +1,9 @@ package com.hideyoshi.backendportfolio.healthChecker.api; +import com.hideyoshi.backendportfolio.util.guard.UserResourceGuard; +import com.hideyoshi.backendportfolio.util.guard.UserResourceGuardEnum; +import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; @@ -11,9 +14,11 @@ @Log4j2 @Controller @RestController +@RequiredArgsConstructor @RequestMapping("/health") public class HealthCheckerController { @RequestMapping + @UserResourceGuard(accessType = UserResourceGuardEnum.OPEN) public ResponseEntity healthCheck() { log.info("Health check requested"); return ResponseEntity.ok("Health check successful!");