From b3762373d4a63c1d7b86366ddc9c07c6723e4fe6 Mon Sep 17 00:00:00 2001 From: "Max W." <66736561+Walzen665@users.noreply.github.com> Date: Fri, 17 Jan 2025 00:44:18 +0100 Subject: [PATCH] finished base auth with spring jpa --- .../biblenotes/rest/mappings/TestMapping.java | 14 ++++++ .../security/JwtAuthenticationFilter.java | 47 +++++++++++-------- .../rest/security/JwtAuthenticationToken.java | 30 ++++++++++++ 3 files changed, 72 insertions(+), 19 deletions(-) create mode 100644 src/main/java/de/w665/biblenotes/rest/mappings/TestMapping.java create mode 100644 src/main/java/de/w665/biblenotes/rest/security/JwtAuthenticationToken.java diff --git a/src/main/java/de/w665/biblenotes/rest/mappings/TestMapping.java b/src/main/java/de/w665/biblenotes/rest/mappings/TestMapping.java new file mode 100644 index 0000000..6494cc4 --- /dev/null +++ b/src/main/java/de/w665/biblenotes/rest/mappings/TestMapping.java @@ -0,0 +1,14 @@ +package de.w665.biblenotes.rest.mappings; + +import de.w665.biblenotes.rest.SecureApiRestController; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TestMapping extends SecureApiRestController { + + @GetMapping("/test") + public String test() { + return "Your authentication works!"; + } +} diff --git a/src/main/java/de/w665/biblenotes/rest/security/JwtAuthenticationFilter.java b/src/main/java/de/w665/biblenotes/rest/security/JwtAuthenticationFilter.java index d36c2a4..ae0cce8 100644 --- a/src/main/java/de/w665/biblenotes/rest/security/JwtAuthenticationFilter.java +++ b/src/main/java/de/w665/biblenotes/rest/security/JwtAuthenticationFilter.java @@ -8,7 +8,6 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; @@ -35,33 +34,43 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { logger.debug("Filtering request: " + request.getRequestURI()); + // Skip filter for all paths except the secure path if(!requestMatcher.matches(request)) { logger.debug("Request does not match the secure path. Skipping JWT authentication."); filterChain.doFilter(request, response); return; } - try { - String jwt = getJwtFromRequest(request); - if (jwt != null && authenticationService.validateToken(jwt)) { - String username = authenticationService.extractSubject(jwt); - // Extract the role from the JWT and set it to Spring AuthenticationContext for access control - String role = authenticationService.getClaimValue(jwt, "role", String.class); - List authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role)); + // Extract the JWT token from the request + String jwt = getJwtFromRequest(request); - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, authorities); - authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); - SecurityContextHolder.getContext().setAuthentication(authentication); - // SUCCESSFUL AUTHENTICATION - filterChain.doFilter(request, response); - } else { - logger.warn("Unauthorized: Authentication token is missing or invalid."); - } - } catch (Exception ex) { - logger.warn("Could not set user authentication in security context. An error occurred during JWT processing.", ex); + if (jwt == null) { // Check if the JWT token is missing + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.setContentType("application/json"); + response.getWriter().write("{\"error\": \"Unauthorized\", \"message\": \"JWT token is missing.\"}"); + logger.warn("Unauthorized: JWT token is missing."); + return; } - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + if (!authenticationService.validateToken(jwt)) { // Validate the JWT token + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.setContentType("application/json"); + response.getWriter().write("{\"error\": \"Unauthorized\", \"message\": \"JWT token is invalid.\"}"); + logger.warn("Unauthorized: JWT token is invalid."); + return; + } + + String username = authenticationService.extractSubject(jwt); + // Extract the role from the JWT and set it to Spring AuthenticationContext for access control + String role = authenticationService.getClaimValue(jwt, "role", String.class); + List authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + role)); + + JwtAuthenticationToken auth = new JwtAuthenticationToken(username, jwt, authorities); + auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(auth); + + // SUCCESSFUL AUTHENTICATION + filterChain.doFilter(request, response); } private String getJwtFromRequest(HttpServletRequest request) { diff --git a/src/main/java/de/w665/biblenotes/rest/security/JwtAuthenticationToken.java b/src/main/java/de/w665/biblenotes/rest/security/JwtAuthenticationToken.java new file mode 100644 index 0000000..96dd2fa --- /dev/null +++ b/src/main/java/de/w665/biblenotes/rest/security/JwtAuthenticationToken.java @@ -0,0 +1,30 @@ +package de.w665.biblenotes.rest.security; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Collection; + +public class JwtAuthenticationToken extends AbstractAuthenticationToken { + + private final String principal; + private final String token; + + public JwtAuthenticationToken(String principal, String token, Collection authorities) { + super(authorities); + this.principal = principal; + this.token = token; + super.setAuthenticated(true); // Set this to true only if authentication is verified + } + + + @Override + public Object getCredentials() { + return null; + } + + @Override + public Object getPrincipal() { + return null; + } +}