From 01f2a8719951f27d918f6d9d28da6dd18ae581b3 Mon Sep 17 00:00:00 2001 From: forge-bot Date: Mon, 13 Jul 2026 10:30:32 +0000 Subject: [PATCH] =?UTF-8?q?=EC=9D=B8=EC=A6=9D/=EA=B6=8C=ED=95=9C=20?= =?UTF-8?q?=EC=97=85=EB=AC=B4=20=EA=B7=9C=EC=B9=99=EA=B3=BC=20=EC=A0=84?= =?UTF-8?q?=ED=99=98=20=EB=B6=88=EB=B3=80=EC=8B=9D=20=EC=B6=94=EC=B6=9C=20?= =?UTF-8?q?(codex-bais-final3-20260713-192718-BAIS-SPRING-ANA-AUTH-001)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/JwtAuthenticationFilter.java | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 auth-migration/src/main/java/com/example/auth/security/JwtAuthenticationFilter.java diff --git a/auth-migration/src/main/java/com/example/auth/security/JwtAuthenticationFilter.java b/auth-migration/src/main/java/com/example/auth/security/JwtAuthenticationFilter.java new file mode 100644 index 0000000..7ad051d --- /dev/null +++ b/auth-migration/src/main/java/com/example/auth/security/JwtAuthenticationFilter.java @@ -0,0 +1,69 @@ +package com.example.auth.security; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; +import java.util.List; + +/** + * JWT Authentication Filter - preserves AUTH-010, AUTH-012 invariants. + * CRITICAL: Tokens only from Authorization header (never URL query). + */ +@Component +public class JwtAuthenticationFilter extends OncePerRequestFilter { + + private static final String AUTHORIZATION_HEADER = "Authorization"; + private static final String BEARER_PREFIX = "Bearer "; + + private final JwtTokenProvider jwtTokenProvider; + + public JwtAuthenticationFilter(JwtTokenProvider jwtTokenProvider) { + this.jwtTokenProvider = jwtTokenProvider; + } + + @Override + protected void doFilterInternal( + HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + + String token = extractToken(request); + + if (token != null && jwtTokenProvider.validateToken(token)) { + JwtTokenProvider.JwtClaims claims = jwtTokenProvider.getClaims(token); + + List authorities = claims.roles().stream() + .map(role -> new SimpleGrantedAuthority("ROLE_" + role)) + .toList(); + + UsernamePasswordAuthenticationToken authentication = + new UsernamePasswordAuthenticationToken(claims.subject(), null, authorities); + + SecurityContextHolder.getContext().setAuthentication(authentication); + } + + filterChain.doFilter(request, response); + } + + private String extractToken(HttpServletRequest request) { + String bearerToken = request.getHeader(AUTHORIZATION_HEADER); + if (bearerToken != null && bearerToken.startsWith(BEARER_PREFIX)) { + return bearerToken.substring(BEARER_PREFIX.length()); + } + return null; + } + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) { + String path = request.getServletPath(); + return path.startsWith("/auth/login") || path.startsWith("/auth/refresh"); + } +}