Merge pull request #42 from HideyoshiSolutions/fixes-auth-filter-health-checker

Fixes Auth Filter for Health Checker
This commit is contained in:
2024-02-16 03:09:40 -03:00
committed by GitHub
4 changed files with 41 additions and 22 deletions

View File

@@ -67,6 +67,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
http.authorizeRequests() http.authorizeRequests()
.antMatchers("/session/**").permitAll() .antMatchers("/session/**").permitAll()
.and().authorizeRequests().antMatchers("/health").permitAll()
.and().authorizeRequests().antMatchers("/user/signup").permitAll() .and().authorizeRequests().antMatchers("/user/signup").permitAll()
.and().authorizeRequests().antMatchers("/user/oauth/**").permitAll() .and().authorizeRequests().antMatchers("/user/oauth/**").permitAll()
.and().authorizeRequests().antMatchers("/user/login/**").permitAll() .and().authorizeRequests().antMatchers("/user/login/**").permitAll()

View File

@@ -2,6 +2,10 @@ package com.hideyoshi.backendportfolio.base.security.filter;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.hideyoshi.backendportfolio.base.security.service.AuthService; 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.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
@@ -11,6 +15,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import static org.springframework.http.HttpHeaders.AUTHORIZATION; import static org.springframework.http.HttpHeaders.AUTHORIZATION;
@@ -20,9 +25,12 @@ import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
public class CustomAuthorizationFilter extends OncePerRequestFilter { public class CustomAuthorizationFilter extends OncePerRequestFilter {
private static final List<String> notProtectedPaths = Arrays.asList( private static final List<String> notProtectedPaths = Arrays.asList(
"/health",
"/user/login", "/user/login",
"/user/signup", "/user/signup",
"/user/login/refresh" "/user/login/refresh",
"/session/validate",
"/session/destroy"
); );
private static final String AUTHORIZATION_TYPE_STRING = "Bearer "; private static final String AUTHORIZATION_TYPE_STRING = "Bearer ";
@@ -38,32 +46,29 @@ public class CustomAuthorizationFilter extends OncePerRequestFilter {
throws ServletException, IOException { throws ServletException, IOException {
if (this.isPathNotProtected(request.getServletPath())) { if (this.isPathNotProtected(request.getServletPath())) {
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
} else { return;
String authorizationHeader = request.getHeader(AUTHORIZATION); }
if (Objects.nonNull(authorizationHeader) && authorizationHeader.startsWith(AUTHORIZATION_TYPE_STRING)) {
try {
UsernamePasswordAuthenticationToken authenticationToken = String authorizationHeader = request.getHeader(AUTHORIZATION);
this.authService.verifyAccessToken(authorizationHeader);
SecurityContextHolder.getContext().setAuthentication(authenticationToken); try {
filterChain.doFilter(request, response); UsernamePasswordAuthenticationToken authenticationToken =
this.validateUserAccess(authorizationHeader);
} catch (Exception e) { SecurityContextHolder.getContext().setAuthentication(authenticationToken);
response.setHeader("error", e.getMessage()); filterChain.doFilter(request, response);
response.setStatus(FORBIDDEN.value()); } catch (Exception e) {
response.setHeader("error", e.getMessage());
response.setStatus(FORBIDDEN.value());
Map<String, String> error = new HashMap<>(); AuthenticationInvalidExceptionDetails error = new AuthenticationInvalidExceptionDetails("Authentication Failed. Check your credentials.",
error.put("error_message", e.getMessage()); HttpStatus.FORBIDDEN.value(), e.getMessage(),
e.getClass().getName(), LocalDateTime.now());
response.setContentType(APPLICATION_JSON_VALUE); response.setContentType(APPLICATION_JSON_VALUE);
new ObjectMapper() new ObjectMapper()
.writeValue(response.getOutputStream(), error); .writeValue(response.getOutputStream(), error);
}
} else {
filterChain.doFilter(request, response);
}
} }
} }
@@ -71,4 +76,11 @@ public class CustomAuthorizationFilter extends OncePerRequestFilter {
return notProtectedPaths.contains(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");
}
}
} }

View File

@@ -2,6 +2,7 @@ package com.hideyoshi.backendportfolio.base.security.interceptor;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.hideyoshi.backendportfolio.base.user.service.UserService; 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.exception.BadRequestException;
import com.hideyoshi.backendportfolio.util.guard.UserResourceGuard; import com.hideyoshi.backendportfolio.util.guard.UserResourceGuard;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@@ -36,7 +37,7 @@ public class UserResourceAccessInterceptor implements HandlerInterceptor {
Boolean accessPermission = Boolean accessPermission =
annotation.accessType().hasAccess(this.userService, this.objectMapper, request); annotation.accessType().hasAccess(this.userService, this.objectMapper, request);
if (!accessPermission) { if (!accessPermission) {
throw new BadRequestException(annotation.denialMessage()); throw new AuthenticationInvalidException(annotation.denialMessage());
} }
} }
return true; return true;

View File

@@ -1,6 +1,9 @@
package com.hideyoshi.backendportfolio.healthChecker.api; 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 lombok.extern.log4j.Log4j2;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@@ -11,9 +14,11 @@ import org.springframework.web.bind.annotation.RestController;
@Log4j2 @Log4j2
@Controller @Controller
@RestController @RestController
@RequiredArgsConstructor
@RequestMapping("/health") @RequestMapping("/health")
public class HealthCheckerController { public class HealthCheckerController {
@RequestMapping @RequestMapping
@UserResourceGuard(accessType = UserResourceGuardEnum.OPEN)
public ResponseEntity<String> healthCheck() { public ResponseEntity<String> healthCheck() {
log.info("Health check requested"); log.info("Health check requested");
return ResponseEntity.ok("Health check successful!"); return ResponseEntity.ok("Health check successful!");