Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat #14 인증 인가 로직 구현 #14

Merged
merged 42 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
bf23d5e
feat: Spring Security Dependency
koreaioi Jan 5, 2025
5101c46
feat: CustomJwtException
koreaioi Jan 6, 2025
e456744
feat: CustomAuthenticationEntryPoint 추가
koreaioi Jan 6, 2025
1faf269
feat: CustomAccessDeniedHandler 추가
koreaioi Jan 6, 2025
23dc33b
feat: JwtAuthenticationFilter 토큰 검증 추가 (미완)
koreaioi Jan 6, 2025
afb8b27
feat: JwtUserDetails 추가
koreaioi Jan 6, 2025
4e7f5e2
feat: JwtUserDetailsService 추가
koreaioi Jan 6, 2025
b54c418
feat: JwtAuthenticationFilter 인증 객체 세션 저장과정 추가
koreaioi Jan 6, 2025
6fd82fc
feat: JwtExtractor - extractJwtToken() 추가
koreaioi Jan 6, 2025
0bb72a3
feat: MemberRepository - findByEmail() 추가
koreaioi Jan 6, 2025
5f1469d
feat: SecurityConfig 추가
koreaioi Jan 6, 2025
9eaddf7
feat: CustomAnnotaion -CurrentMemberId
koreaioi Jan 6, 2025
1511b62
feat: CustomAnnotaion -CurrentMember
koreaioi Jan 6, 2025
089b940
remove: 일부 CustomJwtException 삭제
koreaioi Jan 6, 2025
8f631db
feat: 토큰 재발급 성공 메세지
koreaioi Jan 6, 2025
80e2382
feat: redisUtil.get() Null 반환 예외처리
koreaioi Jan 6, 2025
23baab2
feat: JwtService request에서 쿠키 추출
koreaioi Jan 6, 2025
e3cf22c
fix: 토큰 생성 인자 변경
koreaioi Jan 6, 2025
9171f96
fix: 재발급 관련 에러 메세지 추가
koreaioi Jan 6, 2025
c25c256
fix: JwtService - 토큰 재발급 로직 추가
koreaioi Jan 6, 2025
43fa66b
fix: JwtService - 토큰 재발급 로직 추가
koreaioi Jan 6, 2025
4870d6e
fix: application-local.yml 추가
koreaioi Jan 6, 2025
9d043c7
fix: 쿠키 path 옵션 설정
koreaioi Jan 6, 2025
28f02ee
fix: PermitUrlConfig 반환 변경
koreaioi Jan 6, 2025
12fe042
feat: 재발급 관련 예외 추가
koreaioi Jan 6, 2025
a4b3ff9
Merge branch 'dev' of https://github.com/Leets-Official/GachTaxi-BE i…
koreaioi Jan 6, 2025
3acbfd5
feat: 토큰 만료시 예외 처리
koreaioi Jan 6, 2025
d388252
fix: enum type check @NotNull
koreaioi Jan 6, 2025
9359012
fix: Long type check @NotNull
koreaioi Jan 6, 2025
eb5d617
fix: publicUrl 수정
koreaioi Jan 6, 2025
64bcea1
fix: BEARER 상수 띄어쓰기 수정
koreaioi Jan 6, 2025
4e580c5
remove: Slf4j 삭제
koreaioi Jan 6, 2025
8bd4515
fix: import static HttpStatus
koreaioi Jan 6, 2025
a697244
fix: 개행 추가
koreaioi Jan 6, 2025
bc9fd01
feat: CORS 쿠키 관련 헤더 설정
koreaioi Jan 6, 2025
bba74ad
remove: CurrentMember, JwtUserDetailsService.java 삭제 반영
koreaioi Jan 6, 2025
5df37e0
feat: 토큰 재발급 publicUrl 추가
koreaioi Jan 6, 2025
8004176
fix: JwtUserDetails - 필드 중복 수정
koreaioi Jan 6, 2025
e5ebaf3
fix: getCookie()로 책임 분리
koreaioi Jan 6, 2025
fc9ea01
Merge branch 'dev' of https://github.com/Leets-Official/GachTaxi-BE i…
koreaioi Jan 6, 2025
ca47e03
feat: Merge
koreaioi Jan 7, 2025
fb59c77
feat: Merge
koreaioi Jan 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dependencies {
// Spring
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
// implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-websocket'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
implementation 'org.springframework.boot:spring-boot-starter-validation'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,25 @@

import com.gachtaxi.domain.members.service.AuthService;
import com.gachtaxi.global.auth.enums.OauthLoginStatus;
import com.gachtaxi.global.auth.jwt.dto.JwtTokenDto;
import com.gachtaxi.global.auth.jwt.service.JwtService;
import com.gachtaxi.global.common.response.ApiResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import static com.gachtaxi.domain.members.controller.ResponseMessage.*;
import static com.gachtaxi.global.auth.kakao.dto.KaKaoDTO.*;
import static com.gachtaxi.global.auth.kakao.dto.KaKaoDTO.OauthKakaoResponse;

@RequestMapping("/auth")
@RestController
@RequiredArgsConstructor
public class AuthController {

private final AuthService authService;
private final JwtService jwtService;

@GetMapping("/login/kakao")
public ApiResponse<OauthKakaoResponse> kakaoLogin(@RequestParam("code") String authcode, HttpServletResponse response) {
Expand All @@ -26,4 +30,13 @@ public ApiResponse<OauthKakaoResponse> kakaoLogin(@RequestParam("code") String a
: UN_REGISTER;
return ApiResponse.response(HttpStatus.OK, OAUTH_STATUS.getMessage(), res);
}

@PostMapping("/refresh")
public ApiResponse<Void> reissueRefreshToken(HttpServletRequest request, HttpServletResponse response) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

헤더에서 토큰을 추출할 때 request를 직접 넘겨주기 보다는 @CookieValue, @RequestHeader 등의 어노테이션을 사용해서 쿠키를 가져올 수 있을 것 같아요!

저도 쿠키는 가져와보진 못했지만, 헤더에서 값을 빼올 때는 @RequestHeader를 사용해서 빼오는 것이 해당 컨트롤러에서 필요로 하는 값이 한 눈에 보여서 조은 것 같습니다

JwtTokenDto jwtTokenDto = jwtService.reissueJwtToken(request);

jwtService.setCookie(jwtTokenDto.refreshToken(), response);
jwtService.setHeader(jwtTokenDto.accessToken(), response);
return ApiResponse.response(HttpStatus.OK, REFRESH_TOKEN_REISSUE.getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public enum ResponseMessage {
REGISTER_SUCCESS("회원가입에 성공했습니다."),

// AuthController
REFRESH_TOKEN_REISSUE("토큰 재발급에 성공했습니다."),
LOGIN_SUCCESS("로그인 성공에 성공했습니다."),
UN_REGISTER("회원가입을 진행해주세요");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public record UserSignUpRequestDto(
@NotBlank String email,
@NotBlank String nickName,
@NotBlank String realName,
@NotNull Long studentNumber,
@NotNull Long studentNumber,
@NotNull Gender gender,
@NotNull Boolean termsAgreement,
@NotNull Boolean privacyAgreement,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
@Repository
public interface MemberRepository extends JpaRepository<Members, Long> {

Optional<Members> findByEmail(String email);

Optional<Members> findByStudentNumber(Long studentNumber);

Optional<Members> findByKakaoId(Long kakaoId);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.gachtaxi.global.auth.jwt.annotation;

import org.springframework.security.core.annotation.AuthenticationPrincipal;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : id")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CurrentMemberId 부분도 위 코멘트 내용과 동일합니다 !

Copy link
Member Author

@koreaioi koreaioi Jan 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰 내용을 참고해 코드를 수정해봤는데 검토 부탁드립니다!!

import static com.gachtaxi.global.auth.jwt.annotation.CurrentMemberId.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@AuthenticationPrincipal(expression = "#this == '" + ANONYMOUS_USER + "' ? null : id")
public @interface CurrentMemberId {
    String ANONYMOUS_USER = "anonymousUser";
}

제가 찾은 그나마 깔끔한 방법입니다.
id는 문자열이 아니라 id 자체를 반환해야하므로 String으로 상수화 시키면 null이 반환되더군요!

위 방법은 하드코딩을 지양하고 상수화를 거쳤다는 장점이 있습니다.
그런데 문자열과 + 연산을 사용해 문자열이 계속 생기게 되어 메모리 성능 상 좋지 않을 거 같습니다
그리고 일부는 상수화 일부는 id라는 값 자체를 사용해서 뭔가 어색하기도 하네요....
'anonymousUser'는 @CurrentMemberId 안에서만 사용되기 때문에 유지보수에도 그렇게 어렵지 않을 거 같다는 생각도 듭니다!

혹시 더 나은 개선 방법이 있다면 알려주실 수 있을까요??

Copy link
Member

@huncozyboy huncozyboy Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

anonymousUser를 상수화하는 방식 자체에 대해서는 긍정적으로 생각합니다.
상수화를 통해서 하드코딩된 문자열을 제거하는 방식만으로 진행을 해도 유지보수성이 향상될 수 있다고 생각했습니다.
근데 문자열을 + 연산자로 이어붙이는 방식이 저희는 어노테이션을 사용하는 메소드가 빈번하게 호출될 경우가 있을 수도 있어,
저도 이런 경우에 연산이 성능에 미치게 될 수도 있다고 판단했습니다. 큰 차이는 없다고 생각되긴하지만 최적화를 위해서는 + 연산자 보다는 String.format()이나 StringBuilder를 이용하는 방법이 더 적절하지 않을까 하는 생각은 있습니다 !

public @interface CurrentMemberId {
/*
* AuthenticationPrincipal의 id 필드를 반환
* 즉, JwtUserDetails의 id 필드를 반환
* JwtUserDetails의 id는 Userid
* */
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.gachtaxi.global.auth.jwt.authentication;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.gachtaxi.global.common.response.ApiResponse;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;

import static com.gachtaxi.global.auth.jwt.exception.JwtErrorMessage.JWT_TOKEN_FORBIDDEN;

@Slf4j
@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {

private final static String LOG_FORMAT = "ExceptionClass: {}, Message: {}";
private final static String CONTENT_TYPE = "application/json";
private final static String CHAR_ENCODING = "UTF-8";

@Override
public void handle(HttpServletRequest request, HttpServletResponse response, org.springframework.security.access.AccessDeniedException accessDeniedException) throws IOException, ServletException {
setResponse(response);
log.error(LOG_FORMAT, accessDeniedException.getClass().getSimpleName(), accessDeniedException.getMessage());
}

private void setResponse(HttpServletResponse response) throws IOException {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setContentType(CONTENT_TYPE);
response.setCharacterEncoding(CHAR_ENCODING);

String body = new ObjectMapper().writeValueAsString(ApiResponse.response(HttpStatus.FORBIDDEN, JWT_TOKEN_FORBIDDEN.getMessage()));
response.getWriter().write(body);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.gachtaxi.global.auth.jwt.authentication;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.gachtaxi.global.auth.jwt.exception.JwtErrorMessage;
import com.gachtaxi.global.common.response.ApiResponse;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Slf4j
@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {

private final static String LOG_FORMAT = "ExceptionClass: {}, Message: {}";
private final static String JWT_ERROR = "jwtError";
private final static String CONTENT_TYPE = "application/json";
private final static String CHAR_ENCODING = "UTF-8";

@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
JwtErrorMessage jwtError = (JwtErrorMessage) request.getAttribute(JWT_ERROR);

if (jwtError != null) {
setResponse(response, jwtError.getMessage());
log.error(LOG_FORMAT, jwtError, jwtError.getMessage());
} else {
setResponse(response, authException.getMessage());
log.error(LOG_FORMAT, authException.getClass().getSimpleName(), authException.getMessage());
}
}

private void setResponse(HttpServletResponse response, String message) throws IOException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType(CONTENT_TYPE);
response.setCharacterEncoding(CHAR_ENCODING);

String body = new ObjectMapper().writeValueAsString(ApiResponse.response(HttpStatus.UNAUTHORIZED, message));
response.getWriter().write(body);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.gachtaxi.global.auth.jwt.exception;

import com.gachtaxi.global.common.exception.BaseException;

import static com.gachtaxi.global.auth.jwt.exception.JwtErrorMessage.COOKIE_NOT_FOUND;
import static org.springframework.http.HttpStatus.BAD_REQUEST;

public class CookieNotFoundException extends BaseException {
public CookieNotFoundException() {
super(BAD_REQUEST, COOKIE_NOT_FOUND.getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@
@Getter
@AllArgsConstructor
public enum JwtErrorMessage {
COOKIE_NOT_FOUND("헤더에 쿠키가 없습니다."),
REDIS_NOT_FOUND("Redis 에서 찾을 수 없습니다."),

JWT_TOKEN_UN_VALID("유효하지 않은 토큰 입니다.");
JWT_TOKEN_FORBIDDEN("권한이 없습니다."),
USER_NOT_FOUND_EMAIL("해당 이메일의 유저를 찾을 수 없습니다"),
JWT_TOKEN_NOT_FOUND("토큰을 찾을 수 없습니다"),
JWT_TOKEN_EXPIRED("만료된 토큰입니다."),
JWT_TOKEN_INVALID("유효하지 않은 토큰 입니다.");

private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.gachtaxi.global.auth.jwt.exception;

import com.gachtaxi.global.common.exception.BaseException;

import static com.gachtaxi.global.auth.jwt.exception.JwtErrorMessage.REDIS_NOT_FOUND;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;

public class RefreshTokenNotFoundException extends BaseException {
public RefreshTokenNotFoundException() {
super(UNAUTHORIZED, REDIS_NOT_FOUND.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.gachtaxi.global.auth.jwt.exception;

import com.gachtaxi.global.common.exception.BaseException;

import static com.gachtaxi.global.auth.jwt.exception.JwtErrorMessage.JWT_TOKEN_EXPIRED;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;

public class TokenExpiredException extends BaseException {
public TokenExpiredException() {
super(UNAUTHORIZED, JWT_TOKEN_EXPIRED.getMessage());
}
}

Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.gachtaxi.global.auth.jwt.exception;

import com.gachtaxi.global.common.exception.BaseException;
import static com.gachtaxi.global.auth.jwt.exception.JwtErrorMessage.JWT_TOKEN_UN_VALID;
import static org.springframework.http.HttpStatus.BAD_REQUEST;

import static com.gachtaxi.global.auth.jwt.exception.JwtErrorMessage.JWT_TOKEN_INVALID;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;

public class TokenInvalidException extends BaseException {
public TokenInvalidException() {
super(BAD_REQUEST, JWT_TOKEN_UN_VALID.getMessage());
super(UNAUTHORIZED, JWT_TOKEN_INVALID.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.gachtaxi.global.auth.jwt.exception;

import com.gachtaxi.global.common.exception.BaseException;

import static com.gachtaxi.global.auth.jwt.exception.JwtErrorMessage.USER_NOT_FOUND_EMAIL;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;

public class UserEmailNotFoundException extends BaseException {
public UserEmailNotFoundException() {
super(UNAUTHORIZED, USER_NOT_FOUND_EMAIL.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.gachtaxi.global.auth.jwt.filter;

import com.gachtaxi.global.auth.jwt.user.JwtUserDetails;
import com.gachtaxi.global.auth.jwt.util.JwtExtractor;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Optional;

import static com.gachtaxi.global.auth.jwt.exception.JwtErrorMessage.JWT_TOKEN_EXPIRED;
import static com.gachtaxi.global.auth.jwt.exception.JwtErrorMessage.JWT_TOKEN_NOT_FOUND;

@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter {

private final JwtExtractor jwtExtractor;

private final static String JWT_ERROR = "jwtError";

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 필터에서 JWT 토큰의 유무, 만기 일자만 검증을 하고 토큰의 유효성 검증은 빠져있는 것 같아요!
별도로 토큰에 대한 유효성 검증이 jwtExtractor.getEmail 여기서 일어나고 있는 걸까요!?

필터에서는 조금 더 명시적으로 validate 등의 메서드로 유효성 검증이 표현이 되면 좋을 것 같아요!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞습니다!
조금 더 정확히는 getEmail(), getRole(), isExpired() 등의 메서드가 호출하는 getClaimFromToken()의 parseClaims()에서 유효성 검증이 수행됩니다.

이 메서드는 jwtToken의 유효성 검증 및 디코딩을 수행 후 Claims를 반환합니다!

    private Claims parseClaims(String token) {
        try{
            JwtParser parser = Jwts.parserBuilder()
                    .setSigningKey(key)
                    .build();
            return parser.parseClaimsJws(token).getBody();
        }catch (JwtException e){
            throw new TokenInvalidException();
        }
    }

저는 토큰의 값을 꺼내는 전제 조건이 유효한 토큰이라고 생각했습니다.
Email, Role, Expiration과 같은 Claims를 반환할 때 유효성 검증이 수행되는 JwtParser의 parseClaimsJws를 사용했습니다.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그럼 해당 메서드에 유효성 검증이라는 의미가 들어나도 좋을 것 같아요!
현재 필터만 봤을 때 검증의 역할을 하는 메서드가 확인이 안돼서 jwtExtractor로 내려가서 확인을 할 때 해당 클래스에서도 검증을 하는 메서드는 보이지 않아서 메서드 명이 validateToken 등으로 수정이 되는 것도 좋을 것 같아요

어떻게 보면 추출의 역할은 이 메서드를 호출하는 쪽에서 진행하는 것이니 이 메서드의 책임은 검증이라고 봐도 괜찮을 것 같아서요!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그리고 갑자기 든 생각인데, 현재 jwtExtractor에 구현된 추출 메서드 들은 매번 parseClaims를 거쳐야하는데, 이것이 조금 비 효율적일 수도 있겠다는 생각이 들었어요

가장 초기에 토큰 검증 후에 추출 추출 추출 이렇게 사용할 수 있는게 아니라 토큰 검증+추출 이다보니 id, email 등이 같이 필요할 때는 매번 검증을 할 필요는 없지 않나 라는 생각이 들었습니다!

Optional<String> token = jwtExtractor.extractJwtToken(request);
koreaioi marked this conversation as resolved.
Show resolved Hide resolved

if (token.isEmpty()) {
request.setAttribute(JWT_ERROR, JWT_TOKEN_NOT_FOUND);
filterChain.doFilter(request, response);
return;
}
koreaioi marked this conversation as resolved.
Show resolved Hide resolved

String accessToken = token.get();

if(jwtExtractor.isExpired(accessToken)){
request.setAttribute(JWT_ERROR, JWT_TOKEN_EXPIRED);
filterChain.doFilter(request, response);
return;
}

saveAuthentcation(accessToken);
filterChain.doFilter(request, response);
}

private void saveAuthentcation(String token) {
koreaioi marked this conversation as resolved.
Show resolved Hide resolved
Long id = jwtExtractor.getId(token);
String email = jwtExtractor.getEmail(token);
String role = jwtExtractor.getRole(token);

UserDetails userDetails = JwtUserDetails.of(id, email, role);
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
Loading
Loading