diff --git a/build.gradle b/build.gradle index fd16139..dbace21 100644 --- a/build.gradle +++ b/build.gradle @@ -50,13 +50,6 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' - // auth0 - implementation group: 'com.auth0', name: 'java-jwt', version: '3.18.2' - // https://mvnrepository.com/artifact/com.auth0/auth0-spring-security-api - implementation 'com.auth0:auth0-spring-security-api:1.5.3' - - // import javax.servlet.http.*; - implementation 'javax.servlet:javax.servlet-api:4.0.1' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client:3.2.4' implementation 'org.springframework.security:spring-security-oauth2-client:6.2.3' diff --git a/src/main/java/com/syu/capsbe/global/config/WebSecurityConfig.java b/src/main/java/com/syu/capsbe/global/config/WebSecurityConfig.java index c952045..34db4b4 100644 --- a/src/main/java/com/syu/capsbe/global/config/WebSecurityConfig.java +++ b/src/main/java/com/syu/capsbe/global/config/WebSecurityConfig.java @@ -22,7 +22,7 @@ @RequiredArgsConstructor(access = AccessLevel.PROTECTED) public class WebSecurityConfig { - private final JwtProvider jwtTokenProvider; + private final JwtProvider jwtProvider; @Bean public CorsConfigurationSource corsConfigurationSource() { @@ -52,7 +52,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .requestMatchers("/swagger-ui.html", "/swagger-ui/**", "/api-docs/json", "/v3/api-docs/**", "/v2/api-docs/**", "/v1/api-docs/**", "/swagger-resources/**", "/webjars/**").permitAll() .anyRequest().permitAll() ) - .addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider), + .addFilterBefore(new JwtAuthenticationFilter(jwtProvider), UsernamePasswordAuthenticationFilter.class); return http.build(); } diff --git a/src/main/java/com/syu/capsbe/global/jwt/JwtAuthenticationFilter.java b/src/main/java/com/syu/capsbe/global/jwt/JwtAuthenticationFilter.java index 8cd9799..dad2b5e 100644 --- a/src/main/java/com/syu/capsbe/global/jwt/JwtAuthenticationFilter.java +++ b/src/main/java/com/syu/capsbe/global/jwt/JwtAuthenticationFilter.java @@ -16,7 +16,7 @@ public class JwtAuthenticationFilter extends GenericFilterBean { private static final String AUTHORIZATION_HEADER = "Authorization"; - private static final String TOKEN_PREFIX = "Bearer "; + private static final String TOKEN_PREFIX = "Bearer"; private final JwtProvider jwtProvider; @Override @@ -26,19 +26,17 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha if (token != null && jwtProvider.validateToken(token)) { Authentication authentication = jwtProvider.getAuthentication(token); - if (authentication != null) { - SecurityContextHolder.getContext().setAuthentication(authentication); - } - } + SecurityContextHolder.getContext().setAuthentication(authentication); - chain.doFilter(request, response); + chain.doFilter(request, response); + } } private String resolveToken(HttpServletRequest request) { String bearerToken = request.getHeader(AUTHORIZATION_HEADER); if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) { - return bearerToken.substring(TOKEN_PREFIX.length()); + return bearerToken.substring(7); } return null; diff --git a/src/main/java/com/syu/capsbe/global/jwt/JwtProvider.java b/src/main/java/com/syu/capsbe/global/jwt/JwtProvider.java index d0301ad..ab93cd3 100644 --- a/src/main/java/com/syu/capsbe/global/jwt/JwtProvider.java +++ b/src/main/java/com/syu/capsbe/global/jwt/JwtProvider.java @@ -1,18 +1,16 @@ package com.syu.capsbe.global.jwt; -import com.auth0.jwk.Jwk; -import com.auth0.jwk.JwkProvider; -import com.auth0.jwk.UrlJwkProvider; -import com.auth0.jwt.JWT; -import com.auth0.jwt.interfaces.DecodedJWT; import com.syu.capsbe.global.jwt.dto.JwtResponseDto; import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.MalformedJwtException; import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.UnsupportedJwtException; import io.jsonwebtoken.security.Keys; import java.nio.charset.StandardCharsets; import java.security.Key; -import java.security.interfaces.RSAPublicKey; import java.util.Date; import java.util.List; import lombok.extern.slf4j.Slf4j; @@ -27,20 +25,14 @@ @Component public class JwtProvider { - private final String issuer; - private final UserDetailsService userDetailsService; - private final JwkProvider jwkProvider; private static final long TOKEN_VALID_TIME = 30 * 60 * 1000L; // 30 minutes + private final UserDetailsService userDetailsService; private final Key secretKey; - public JwtProvider( - @Value("${auth0.domain}") String issuer, UserDetailsService userDetailsService, - @Value("${JWT_KEY}") String secretKey + public JwtProvider(UserDetailsService userDetailsService, @Value("${JWT_KEY}") String secretKey ) { this.secretKey = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8)); - this.issuer = issuer; this.userDetailsService = userDetailsService; - this.jwkProvider = new UrlJwkProvider(issuer); } public JwtResponseDto generateToken(String email, List roles) { @@ -60,40 +52,34 @@ public JwtResponseDto generateToken(String email, List roles) { return JwtResponseDto.of(accessToken, expiresAt); } - public Authentication getAuthentication(String token) { - try { - DecodedJWT jwt = verifyToken(token); - String email = jwt.getSubject(); - - UserDetails userDetails = userDetailsService.loadUserByUsername(email); - return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); - } catch (Exception e) { - log.error("JWT 검증 실패", e); - return null; - } + public Authentication getAuthentication(String accessToken) { + UserDetails userDetails = userDetailsService.loadUserByUsername( + this.getUserEmailByToken(accessToken)); + return new UsernamePasswordAuthenticationToken(userDetails, "", + userDetails.getAuthorities()); } - public DecodedJWT verifyToken(String token) throws Exception { - DecodedJWT decodedJWT = JWT.decode(token); - - Jwk jwk = jwkProvider.get(decodedJWT.getKeyId()); - RSAPublicKey publicKey = (RSAPublicKey) jwk.getPublicKey(); - - com.auth0.jwt.algorithms.Algorithm algorithm = com.auth0.jwt.algorithms.Algorithm.RSA256(publicKey, null); - com.auth0.jwt.JWTVerifier verifier = JWT.require(algorithm) - .withIssuer(issuer) - .build(); - - return verifier.verify(token); - } public boolean validateToken(String token) { try { - verifyToken(token); - return true; - } catch (Exception e) { - log.error("Invalid JWT Token", e); - return false; + Jws claims = Jwts.parserBuilder() + .setSigningKey(secretKey) + .build() + .parseClaimsJws(token); + return !claims.getBody().getExpiration().before(new Date()); + } catch (SecurityException | MalformedJwtException e) { + log.info("Invalid JWT Token", e); + } catch (ExpiredJwtException e) { + log.info("Expired JWT Token", e); + } catch (UnsupportedJwtException e) { + log.info("Unsupported JWT Token", e); + } catch (IllegalArgumentException e) { + log.info("JWT claims string is empty.", e); } + return false; + } + + public String getUserEmailByToken(String token) { + return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); } }