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] 카카오 로그인 구현 및 사용자 인증 방식 개선 #179

Merged
merged 79 commits into from
Sep 21, 2024
Merged
Show file tree
Hide file tree
Changes from 68 commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
c6fd23a
[RENAME] getClaim으로 rename
Kim-TaeUk Sep 7, 2024
73132e4
[REMOVE] 불필요한 주석 제거
Kim-TaeUk Sep 7, 2024
8ce9487
[RENAME] from generateToken to generateJWT
Kim-TaeUk Sep 7, 2024
4bb0ea5
[RENAME] from JWT_SECRET to JWT_SECRET_KEY
Kim-TaeUk Sep 7, 2024
e2bc2d3
[REFACTOR] generateJWT 메서드에서 claim 생성 책임 분리
Kim-TaeUk Sep 7, 2024
1af15cc
[FIX] signature algorithm 명시
Kim-TaeUk Sep 7, 2024
cfb89c0
[RENAME] from getUserFromJwt to getUserIdFromJwt
Kim-TaeUk Sep 7, 2024
9f87ece
[REMOVE] 불필요한 개행 제거
Kim-TaeUk Sep 7, 2024
4e503bf
[FIX] Base64 인코딩 중복 작업 제거
Kim-TaeUk Sep 7, 2024
db1bc1d
[RENAME] from validateToken to validateJWT
Kim-TaeUk Sep 7, 2024
85d8018
[REFACTOR] 메서드 순서 조정
Kim-TaeUk Sep 7, 2024
9fba912
[REFACTOR] 여러번 호출되는 currentTimeMillis() 변수로 추출
Kim-TaeUk Sep 7, 2024
842ceae
[RENAME] 불명확한 USER_ID를 CLAIM_USER_ID로 rename
Kim-TaeUk Sep 7, 2024
203e2c4
[REMOVE] 불필요한 주석 제거
Kim-TaeUk Sep 8, 2024
e4c1f10
[REFACTOR] access token 만료시간 yml 통해서 주입받는 방식으로 변경
Kim-TaeUk Sep 8, 2024
ea03380
[FEAT] refresh token 만료시간 yml 통해서 주입받는 방식으로 추가
Kim-TaeUk Sep 8, 2024
892633d
[FIX] generateJWT에서 expirationTime을 외부에서 입력 받도록 변경
Kim-TaeUk Sep 8, 2024
b4018f1
[FEAT] 토큰에 따른 세부 구현 메서드 추가
Kim-TaeUk Sep 8, 2024
e07d2ec
[FIX] 응답으로 내려주는 JWT 프로퍼티 키 이름 변경
Kim-TaeUk Sep 8, 2024
161fb87
[FIX] access token 발급 메서드 변경
Kim-TaeUk Sep 8, 2024
3a4485b
[RENAME] accessToken으로 rename
Kim-TaeUk Sep 8, 2024
50c312b
[FEAT] refreshToken 발급 및 응답에 추가
Kim-TaeUk Sep 8, 2024
cbb59d5
[FIX] 임시로 UserService에서 엑세스 토큰 발급 시 호출하는 메서드 수정
Kim-TaeUk Sep 8, 2024
d59ab20
[REFACTOR] JWT validation 결과 변수로 추출
Kim-TaeUk Sep 9, 2024
3c31049
[FEAT] Access token 만료 시 error response 내려주는 로직 추가
Kim-TaeUk Sep 9, 2024
9ee9bde
[STYLE] 파일 끝 개행 추가
Kim-TaeUk Sep 9, 2024
e28d6d6
[FEAT] reissue 엔드포인트 추가
Kim-TaeUk Sep 9, 2024
a1cf735
[FEAT] reissue 요청 및 응답 dto 추가
Kim-TaeUk Sep 9, 2024
a4164d6
[FEAT] service layer에서 valid한 refresh token인 경우 reissue 로직 추가
Kim-TaeUk Sep 9, 2024
071ffc8
[FEAT] expired refresh token인 경우 예외 로직 추가
Kim-TaeUk Sep 9, 2024
9f69a22
[FEAT] invalid refresh token인 경우 예외 로직 추가
Kim-TaeUk Sep 9, 2024
b0167fe
[FEAT] CustomAuthError 추가
Kim-TaeUk Sep 9, 2024
a6d9f9e
[FEAT] CustomAuthException 추가
Kim-TaeUk Sep 9, 2024
5cdc836
[FEAT] 인증 제외 엔드포인트에 /reissue 추가
Kim-TaeUk Sep 9, 2024
6779aef
[FIX] RTR(refresh token rotation)을 위해 응답 dto에 프로퍼티 추가
Kim-TaeUk Sep 9, 2024
3721ea8
[FEAT] 새로운 refresh token 발급 로직 추가
Kim-TaeUk Sep 9, 2024
c742c55
[FIX] jwt 생성 시 claim에 tokenType을 subject로 추가
Kim-TaeUk Sep 9, 2024
e14326b
[FEAT] tokenType 확인 메서드 추가
Kim-TaeUk Sep 9, 2024
928b1cf
[FEAT] reissue시, tokenType 확인 로직 추가
Kim-TaeUk Sep 9, 2024
1faf2d3
[REMOVE] JwtProvider에서 토큰 검증 및 정보 추출 로직 삭제
Kim-TaeUk Sep 9, 2024
ab181b7
[FEAT] JwtProvider에서 삭제한 토큰 검증 및 정보 추출 로직 책임을 갖는 JWTUtil 추가
Kim-TaeUk Sep 9, 2024
4f99b2b
[FIX] CLAIM_USER_ID와 getSigningKey()를 JWTUtil에서 사용할 수 있도록 접근자 변경
Kim-TaeUk Sep 9, 2024
1fd08c5
[FEAT] AuthService에서 JWTUtil 의존성 주입
Kim-TaeUk Sep 9, 2024
7fa2966
[FEAT] JwtAuthenticationFilter에서 JWTUtil 의존성 주입
Kim-TaeUk Sep 9, 2024
270c9bb
[REFACTOR] 토큰 검증 및 정보 추출 로직 jwtUtil에 의존하도록 변경
Kim-TaeUk Sep 9, 2024
94b20cc
[REMOVE] 사용하지 않는 JwtProvider 의존성 삭제
Kim-TaeUk Sep 9, 2024
ddf949c
[FEAT] 온보딩 진행 여부 체크 변수 추가
Kim-TaeUk Sep 10, 2024
aa7e7fa
[FEAT] 응답에 isRegister 프로퍼티 추가
Kim-TaeUk Sep 10, 2024
abfa7a0
[CHORE] lettuce 의존성 추가
Kim-TaeUk Sep 10, 2024
d6d4fe7
[CHORE] spring-data-redis 의존성 추가
Kim-TaeUk Sep 10, 2024
7cf8a1a
[FEAT] RefreshToken 엔티티 추가
Kim-TaeUk Sep 10, 2024
99c0618
[FEAT] RefreshTokenRepository 추가
Kim-TaeUk Sep 10, 2024
73fa63a
[FEAT] CustomAuthenticationSuccessHandler에 refreshTokenRepository 의존관…
Kim-TaeUk Sep 10, 2024
50c7d54
[FEAT] 로그인 성공 시 발급하는 refresh token redis에 저장
Kim-TaeUk Sep 10, 2024
6a9676f
[FEAT] AuthService에 refreshTokenRepository 의존관계 주입
Kim-TaeUk Sep 10, 2024
0f9620d
[FEAT] Application 클래스에 @EnableRedisRepositories 추가
Kim-TaeUk Sep 10, 2024
2cafece
[STYLE] 코드 포맷팅
Kim-TaeUk Sep 10, 2024
6feefe6
[FEAT] refresh token으로 issue 시, 서버 측에서 저장 여부 확인 로직 추가
Kim-TaeUk Sep 10, 2024
216aa3e
[FEAT] reissue시 RTR
Kim-TaeUk Sep 10, 2024
54646a1
[FIX] token type 확인 로직 제거
Kim-TaeUk Sep 10, 2024
241e57e
[FEAT] 만료된 refresh일 때 발생하는 에러 정의
Kim-TaeUk Sep 10, 2024
366b197
[REMOVE] 토큰 타입 확인하는 메서드 제거 - 사용하지 않음
Kim-TaeUk Sep 10, 2024
321299f
[FIX] hash 데이터 TTL 만료 시, set 데이터도 삭제되도록 Redis keyspace 이벤트 활성화
Kim-TaeUk Sep 10, 2024
cdb5388
[FEAT] refresh token TTL 설정 추가
Kim-TaeUk Sep 10, 2024
e42e17a
[REMOVE] 불필요한 주석 제거
Kim-TaeUk Sep 14, 2024
516f1c9
[FIX] 필터에서 체크 - valid한 access token일 경우로 수정
Kim-TaeUk Sep 14, 2024
43867df
[FIX] JwtValidationType 분류 세분화
Kim-TaeUk Sep 14, 2024
15a3d0f
[FIX] valid한 token인 경우 분류 세분화
Kim-TaeUk Sep 14, 2024
e0c32de
[FIX] JwtValidationType 분류 세분화
Kim-TaeUk Sep 14, 2024
194d753
[FIX] expired token인 경우 분류 세분화
Kim-TaeUk Sep 14, 2024
9b10fee
[FIX] reissue시 성공 조건 분류 세분화
Kim-TaeUk Sep 14, 2024
5c2868e
[FIX] reissue시 만료된 refresh로 분류 세분화
Kim-TaeUk Sep 14, 2024
2439cdd
[FIX] 인증 시 만료된 access로 분류 세분화
Kim-TaeUk Sep 14, 2024
8986926
[FIX] access 만료 시 응답 변경
Kim-TaeUk Sep 14, 2024
90a7cdf
[REFACTOR] reissue 예외 처리 간소화
Kim-TaeUk Sep 14, 2024
d7c12a7
[REMOVE] 사용하지 않는 CustomAuthError 삭제
Kim-TaeUk Sep 14, 2024
1134327
[REMOVE] 의미 없는 개행 제거
Kim-TaeUk Sep 14, 2024
307e579
[REMOVE] 불필요한 개행 제거
Kim-TaeUk Sep 19, 2024
fe1a758
[RENAME] memberId를 userId로 rename
Kim-TaeUk Sep 20, 2024
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
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ dependencies {

//spring boot oauth2
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

// Lettuce for Java Redis client
implementation 'io.lettuce:lettuce-core:6.3.2.RELEASE'

// spring data redis
implementation 'org.springframework.data:spring-data-redis:3.3.2'
Kim-TaeUk marked this conversation as resolved.
Show resolved Hide resolved
}

tasks.named('test') {
Expand Down
9 changes: 6 additions & 3 deletions src/main/java/org/websoso/WSSServer/WssServerApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.redis.core.RedisKeyValueAdapter;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableScheduling
@EnableRedisRepositories(enableKeyspaceEvents = RedisKeyValueAdapter.EnableKeyspaceEvents.ON_STARTUP)
Kim-TaeUk marked this conversation as resolved.
Show resolved Hide resolved
@SpringBootApplication
public class WssServerApplication {

public static void main(String[] args) {
SpringApplication.run(WssServerApplication.class, args);
}
public static void main(String[] args) {
SpringApplication.run(WssServerApplication.class, args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public class SecurityConfig {
"/feeds/popular",
"/users/{userId}/feeds",
"/users/profile/{userId}",
"/{userId}/preferences/genres"
"/{userId}/preferences/genres",
"/reissue"
};

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ private void setResponse(HttpServletResponse response) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}

}
}
50 changes: 50 additions & 0 deletions src/main/java/org/websoso/WSSServer/config/jwt/JWTUtil.java
Kim-TaeUk marked this conversation as resolved.
Show resolved Hide resolved
rinarina0429 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.websoso.WSSServer.config.jwt;

import static org.websoso.WSSServer.config.jwt.JwtProvider.CLAIM_USER_ID;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class JWTUtil {

private final JwtProvider jwtProvider;

public Long getUserIdFromJwt(String token) {
Claims claims = getClaim(token);
return Long.valueOf(claims.get(CLAIM_USER_ID).toString());
}

public JwtValidationType validateJWT(String token) {
try {
final Claims claims = getClaim(token);
String tokenType = claims.getSubject();
if (tokenType.equals("access")) {
return JwtValidationType.VALID_ACCESS;
}
return JwtValidationType.VALID_REFRESH;
Kim-TaeUk marked this conversation as resolved.
Show resolved Hide resolved
} catch (MalformedJwtException ex) {
return JwtValidationType.INVALID_TOKEN;
} catch (ExpiredJwtException ex) {
return JwtValidationType.EXPIRED_TOKEN;
} catch (UnsupportedJwtException ex) {
return JwtValidationType.UNSUPPORTED_TOKEN;
} catch (IllegalArgumentException ex) {
return JwtValidationType.EMPTY_TOKEN;
}
}

private Claims getClaim(final String token) {
return Jwts.parserBuilder()
.setSigningKey(jwtProvider.getSigningKey())
.build()
.parseClaimsJws(token)
.getBody();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.websoso.WSSServer.config.jwt;

import static org.websoso.WSSServer.config.jwt.JwtValidationType.VALID_TOKEN;
import static org.websoso.WSSServer.config.jwt.JwtValidationType.EXPIRED_TOKEN;
import static org.websoso.WSSServer.config.jwt.JwtValidationType.VALID_ACCESS;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
Expand All @@ -23,20 +24,23 @@
public class JwtAuthenticationFilter extends OncePerRequestFilter {

private final static String TOKEN_PREFIX = "Bearer ";
private final JwtProvider jwtProvider;
private final JWTUtil jwtUtil;

@Override
protected void doFilterInternal(@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain) throws ServletException, IOException {
try {
final String token = getJwtFromRequest(request);
if (jwtProvider.validateToken(token) == VALID_TOKEN) {
Long memberId = jwtProvider.getUserFromJwt(token);
// authentication 객체 생성 -> principal에 유저정보를 담는다.
final JwtValidationType validationResult = jwtUtil.validateJWT(token);
if (validationResult == VALID_ACCESS) {
Long memberId = jwtUtil.getUserIdFromJwt(token);
UserAuthentication authentication = new UserAuthentication(memberId.toString(), null, null);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
Kim-TaeUk marked this conversation as resolved.
Show resolved Hide resolved
} else if (validationResult == EXPIRED_TOKEN) {
handleExpiredAccessToken(request, response);
return;
}
} catch (Exception exception) {
try {
Expand All @@ -45,7 +49,6 @@ protected void doFilterInternal(@NonNull HttpServletRequest request,
throw new RuntimeException(e);
}
}
// 다음 필터로 요청 전달
filterChain.doFilter(request, response);
}

Expand All @@ -56,4 +59,11 @@ private String getJwtFromRequest(HttpServletRequest request) {
}
return null;
}
}

private void handleExpiredAccessToken(HttpServletRequest request,
HttpServletResponse response) throws IOException {
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("{\"error\": \"Access Token Expired. Use Refresh Token to reissue.\"}");
}
}
80 changes: 31 additions & 49 deletions src/main/java/org/websoso/WSSServer/config/jwt/JwtProvider.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package org.websoso.WSSServer.config.jwt;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Header;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import jakarta.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
Expand All @@ -21,66 +19,50 @@
@RequiredArgsConstructor
public class JwtProvider {

private static final String USER_ID = "userId";
private static final Long TOKEN_EXPIRATION_TIME = 6 * 30 * 24 * 60 * 60 * 1000L; // 6개월
protected static final String CLAIM_USER_ID = "userId";

@Value("${jwt.secret}")
private String JWT_SECRET;
private String JWT_SECRET_KEY;

@Value("${jwt.expiration-time.access-token}")
private Long ACCESS_TOKEN_EXPIRATION_TIME;

@Value("${jwt.expiration-time.refresh-token}")
private Long REFRESH_TOKEN_EXPIRATION_TIME;
Kim-TaeUk marked this conversation as resolved.
Show resolved Hide resolved

@PostConstruct
protected void init() {
//base64 라이브러리에서 encodeToString을 이용해서 byte[] 형식을 String 형식으로 변환
JWT_SECRET = Base64.getEncoder().encodeToString(JWT_SECRET.getBytes(StandardCharsets.UTF_8));
JWT_SECRET_KEY = Base64.getEncoder().encodeToString(JWT_SECRET_KEY.getBytes(StandardCharsets.UTF_8));
}

public String generateToken(Authentication authentication) {
final Date now = new Date();

final Claims claims = Jwts.claims()
.setIssuedAt(now)
.setExpiration(new Date(now.getTime() + TOKEN_EXPIRATION_TIME)); // 만료 시간
public String generateAccessToken(Authentication authentication) {
return generateJWT(authentication, ACCESS_TOKEN_EXPIRATION_TIME, "access");
}

claims.put(USER_ID, authentication.getPrincipal());
public String generateRefreshToken(Authentication authentication) {
return generateJWT(authentication, REFRESH_TOKEN_EXPIRATION_TIME, "refresh");
}

public String generateJWT(Authentication authentication, Long expirationTime, String tokenType) {
return Jwts.builder()
.setHeaderParam(Header.TYPE, Header.JWT_TYPE) // Header
.setClaims(claims) // Claim
.signWith(getSigningKey()) // Signature
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
.setClaims(generateClaims(authentication, expirationTime, tokenType))
.signWith(getSigningKey(), SignatureAlgorithm.HS256)
Kim-TaeUk marked this conversation as resolved.
Show resolved Hide resolved
.compact();
}

private SecretKey getSigningKey() {
String encodedKey = Base64.getEncoder().encodeToString(JWT_SECRET.getBytes()); //SecretKey 통해 서명 생성
return Keys.hmacShaKeyFor(
encodedKey.getBytes()); //일반적으로 HMAC (Hash-based Message Authentication Code) 알고리즘 사용
}

public JwtValidationType validateToken(String token) {
try {
final Claims claims = getBody(token);
return JwtValidationType.VALID_TOKEN;
} catch (MalformedJwtException ex) {
return JwtValidationType.INVALID_TOKEN;
} catch (ExpiredJwtException ex) {
return JwtValidationType.EXPIRED_TOKEN;
} catch (UnsupportedJwtException ex) {
return JwtValidationType.UNSUPPORTED_TOKEN;
} catch (IllegalArgumentException ex) {
return JwtValidationType.EMPTY_TOKEN;
}
}
private Claims generateClaims(Authentication authentication, Long expirationTime, String tokenType) {
long now = System.currentTimeMillis();
final Claims claims = Jwts.claims()
.setSubject(tokenType)
Kim-TaeUk marked this conversation as resolved.
Show resolved Hide resolved
.setIssuedAt(new Date(now))
.setExpiration(new Date(now + expirationTime));
claims.put(CLAIM_USER_ID, authentication.getPrincipal());

private Claims getBody(final String token) {
return Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody();
return claims;
}

public Long getUserFromJwt(String token) {
Claims claims = getBody(token);
return Long.valueOf(claims.get(USER_ID).toString());
protected SecretKey getSigningKey() {
return Keys.hmacShaKeyFor(JWT_SECRET_KEY.getBytes());
}

}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package org.websoso.WSSServer.config.jwt;

public enum JwtValidationType {
VALID_TOKEN, // 유효한 JWT
INVALID_SIGNATURE, // 유효하지 않은 서명
INVALID_TOKEN, // 유효하지 않은 토큰
EXPIRED_TOKEN, // 만료된 토큰
UNSUPPORTED_TOKEN, // 지원하지 않는 형식의 토큰
EMPTY_TOKEN // 빈 JWT
VALID_ACCESS,
VALID_REFRESH,
INVALID_TOKEN,
EXPIRED_TOKEN,
UNSUPPORTED_TOKEN,
EMPTY_TOKEN
}
27 changes: 27 additions & 0 deletions src/main/java/org/websoso/WSSServer/controller/AuthController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.websoso.WSSServer.controller;

import static org.springframework.http.HttpStatus.OK;

import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.websoso.WSSServer.dto.auth.ReissueRequest;
import org.websoso.WSSServer.dto.auth.ReissueResponse;
import org.websoso.WSSServer.service.AuthService;

@RestController
@RequiredArgsConstructor
public class AuthController {

private final AuthService authService;

@PostMapping("/reissue")
public ResponseEntity<ReissueResponse> reissue(@RequestBody ReissueRequest reissueRequest) {
String refreshToken = reissueRequest.refreshToken();
return ResponseEntity
.status(OK)
.body(authService.reissue(refreshToken));
}
}
17 changes: 17 additions & 0 deletions src/main/java/org/websoso/WSSServer/domain/RefreshToken.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.websoso.WSSServer.domain;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;

@Getter
@AllArgsConstructor
@RedisHash(value = "refreshToken", timeToLive = 60 * 60 * 24 * 7 * 2)
Kim-TaeUk marked this conversation as resolved.
Show resolved Hide resolved
ChaeAg marked this conversation as resolved.
Show resolved Hide resolved
public class RefreshToken {

@Id
private String refreshToken;

private Long userId;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.websoso.WSSServer.dto.auth;

public record ReissueRequest(
String refreshToken
) {
}
11 changes: 11 additions & 0 deletions src/main/java/org/websoso/WSSServer/dto/auth/ReissueResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.websoso.WSSServer.dto.auth;

public record ReissueResponse(
String Authorization,
ChaeAg marked this conversation as resolved.
Show resolved Hide resolved
String refreshToken
) {

public static ReissueResponse of(String accessToken, String refreshToken) {
return new ReissueResponse(accessToken, refreshToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.websoso.WSSServer.exception.error;

import static org.springframework.http.HttpStatus.UNAUTHORIZED;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import org.websoso.WSSServer.exception.common.ICustomError;

@Getter
@AllArgsConstructor
public enum CustomAuthError implements ICustomError {

EXPIRED_REFRESH_TOKEN("AUTH-001", "만료된 리프레시 토큰입니다.", UNAUTHORIZED),
INVALID_TOKEN("AUTH-002", "유효하지 않은 토큰입니다.", UNAUTHORIZED),
INVALID_REFRESH_TOKEN("AUTH-003", "등록되지 않은 리프레시 토큰입니다.", UNAUTHORIZED);

private final String code;
private final String description;
private final HttpStatus statusCode;
}

ChaeAg marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.websoso.WSSServer.exception.exception;

import lombok.Getter;
import org.websoso.WSSServer.exception.common.AbstractCustomException;
import org.websoso.WSSServer.exception.error.CustomAuthError;

@Getter
public class CustomAuthException extends AbstractCustomException {

public CustomAuthException(CustomAuthError customAuthError, String message) {
super(customAuthError, message);
}
}
Loading
Loading