Skip to content

Commit

Permalink
Merge pull request #12 from lotteon2/dev-auth-refactoring
Browse files Browse the repository at this point in the history
kafka dependency 추가
  • Loading branch information
nowgnas authored Dec 7, 2023
2 parents 4adc32c + eb4067e commit 04b130e
Show file tree
Hide file tree
Showing 26 changed files with 139 additions and 120 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy-dev.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
on:
push:
branches:
- 'develop'
- 'dev'
jobs:
build-and-push-docker-image:
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ dependencies {
testImplementation 'com.h2database:h2:2.1.214'
implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
implementation 'org.springframework.kafka:spring-kafka'
}

dependencyManagement {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public ResponseEntity<String> renewRefreshToken(
String accessToken = renewRefreshTokenStrategy.renew(renewAccessTokenDto.getAuthId(),
renewAccessTokenDto.getRole(),
request, response);
response.addHeader(SecurityPolicyStaticValue.TOKEN_AUTHORIZAION_HEADER_NAME,
response.addHeader(SecurityPolicyStaticValue.TOKEN_AUTHORIZATION_HEADER_NAME,
SecurityPolicyStaticValue.TOKEN_AUTHORIZATION_PREFIX + accessToken);
return ResponseEntity.ok("재발급 완료");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import com.bit.lot.flower.auth.common.dto.RenewAccessTokenDto;
import com.bit.lot.flower.auth.common.exception.ErrorDTO;
import com.bit.lot.flower.auth.common.util.JsonBinderUtil;
import com.bit.lot.flower.auth.common.valueobject.AuthId;
import com.bit.lot.flower.auth.common.valueobject.Role;
import com.bit.lot.flower.auth.common.valueobject.SecurityPolicyStaticValue;
import com.bit.lot.flower.auth.common.valueobject.AuthId;
import io.jsonwebtoken.ExpiredJwtException;
import java.io.IOException;
import javax.servlet.FilterChain;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.bit.lot.flower.auth.common.util.RedisRefreshTokenUtil;
import com.bit.lot.flower.auth.common.valueobject.SecurityPolicyStaticValue;
import java.time.Duration;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
Expand All @@ -14,18 +13,17 @@

@RequiredArgsConstructor
@Component
public class IssueRefreshRefreshTokenInCookie implements
RefreshTokenStrategy {
public class IssueRefreshRefreshTokenInCookie implements RefreshTokenStrategy {

@Value("${cookie.refresh.http.domain}")
private String domain;
private String domain;
@Value("${cookie.refresh.token.name}")
private String refreshCookieName;
private String refreshCookieName;

private final RedisRefreshTokenUtil redisRefreshTokenUtil;

@Override
public void createRefreshToken(String userId,HttpServletResponse response) {
public void createRefreshToken(String userId, HttpServletResponse response) {
String refreshToken = JwtUtil.generateRefreshToken(String.valueOf(userId));
redisRefreshTokenUtil.saveRefreshToken(userId, refreshToken,
Long.parseLong(SecurityPolicyStaticValue.REFRESH_EXPIRATION_TIME));
Expand All @@ -39,9 +37,5 @@ public void invalidateRefreshToken(String id, HttpServletResponse response) {
redisRefreshTokenUtil.deleteRefreshToken(id);
}

@Override
public void renewRefreshToken(String id, HttpServletResponse response) {

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

@Component
public interface RefreshTokenStrategy {
public void createRefreshToken(String id, HttpServletResponse response);
public void invalidateRefreshToken(String id, HttpServletResponse response);
public void renewRefreshToken(String id, HttpServletResponse response);
public void createRefreshToken(String userId, HttpServletResponse response);
public void invalidateRefreshToken(String userId, HttpServletResponse response);
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo
Authentication authentication) {
String token = tokenHandler.createToken(getIdFromPrincipal(authentication),
createClaimsRoleMap(), response);
response.setHeader(SecurityPolicyStaticValue.TOKEN_AUTHORIZAION_HEADER_NAME,SecurityPolicyStaticValue.TOKEN_AUTHORIZATION_PREFIX +token );
response.setHeader(SecurityPolicyStaticValue.TOKEN_AUTHORIZATION_HEADER_NAME,SecurityPolicyStaticValue.TOKEN_AUTHORIZATION_PREFIX +token );
}

private String getIdFromPrincipal(Authentication authentication){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ private ExtractAuthorizationTokenUtil() {
public static String extractToken(HttpServletRequest request) {

String authorizationHeader = request.getHeader(
SecurityPolicyStaticValue.TOKEN_AUTHORIZAION_HEADER_NAME);
SecurityPolicyStaticValue.TOKEN_AUTHORIZATION_HEADER_NAME);
if (authorizationHeader != null && authorizationHeader.startsWith(SecurityPolicyStaticValue.TOKEN_AUTHORIZATION_PREFIX)) {
return authorizationHeader.substring(7);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.time.Instant;
import java.util.Date;
import java.util.HashMap;
Expand Down Expand Up @@ -37,7 +36,7 @@ public static String generateAccessTokenWithClaims(String subject,
return Jwts.builder()
.setSubject(subject)
.setIssuedAt(now)
.setExpiration(Date.from(Instant.now().plusMillis(
.setExpiration(Date.from(Instant.now().plusSeconds(
Long.parseLong(SecurityPolicyStaticValue.ACCESS_EXPIRATION_TIME))))
.signWith(accessSecret)
.addClaims(claimsList)
Expand All @@ -58,7 +57,7 @@ public static Map<String, Object> addClaims(String id, Object value) {
return Jwts.builder()
.setSubject(subject)
.setIssuedAt(now)
.setExpiration(Date.from(Instant.now().plusMillis(
.setExpiration(Date.from(Instant.now().plusSeconds(
Long.parseLong(SecurityPolicyStaticValue.ACCESS_EXPIRATION_TIME))))
.signWith(accessSecret)
.compact();
Expand All @@ -71,7 +70,7 @@ public static String generateRefreshToken(String subject) {
return Jwts.builder()
.setSubject(subject)
.setIssuedAt(now)
.setExpiration(Date.from(Instant.now().plusMillis(
.setExpiration(Date.from(Instant.now().plusSeconds(
Long.parseLong(SecurityPolicyStaticValue.REFRESH_EXPIRATION_TIME))))
.signWith(refreshSecret)
.compact();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
public class SecurityPolicyStaticValue {

public static String REFRESH_EXPIRATION_TIME="3660";
public static String TOKEN_AUTHORIZAION_HEADER_NAME = "Authorization";
public static String TOKEN_AUTHORIZATION_HEADER_NAME = "Authorization";
public static String TOKEN_AUTHORIZATION_PREFIX= "Bearer ";
public static String CLAIMS_ROLE_KEY_NAME = "ROLE";
public static String ACCESS_EXPIRATION_TIME="10";
public static String ACCESS_EXPIRATION_TIME="3600";


}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ AuthenticationManager socialAuthenticationManager() {
UsernamePasswordAuthenticationFilter socialAuthenticationFilter() {
SocialAuthenticationFilter socialAuthenticationFilter = new SocialAuthenticationFilter(systemAuthenticationSuccessHandler,
socialAuthenticationManager());
socialAuthenticationFilter.setFilterProcessesUrl("/api/auth/social/**/login");
socialAuthenticationFilter.setFilterProcessesUrl("/**/social/login");
socialAuthenticationFilter.setAuthenticationSuccessHandler(systemAuthenticationSuccessHandler);
return socialAuthenticationFilter;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class SocialAuthRestController {

@ApiOperation(value = "유저 로그인", notes = "Authroization: Bearer 토큰 생성, Refresh토큰"
+ "Redis에 생성, HttpOnlyCookie에 생성")
@PostMapping("/api/auth/social/login")
@PostMapping("/social/login")
public ResponseEntity<UserFeignLoginResponse> loginWithUserServiceResponse(
HttpServletRequest request) {
SocialLoginRequestCommand dto = (SocialLoginRequestCommand) request.getAttribute("command");
Expand All @@ -41,7 +41,7 @@ public ResponseEntity<UserFeignLoginResponse> loginWithUserServiceResponse(

@ApiOperation(value = "유저 로그아웃", notes = "Authroization: Bearer 토큰 제거, Refresh토큰"
+ "Redis에서 제거, HttpOnlyCookie에서 제거")
@PostMapping("/api/auth/social/{provider}/logout")
@PostMapping("/social/{provider}/logout")
public ResponseEntity<String> logout(
@AuthenticationPrincipal String socialId,
@PathVariable AuthenticationProvider provider) {
Expand All @@ -53,7 +53,7 @@ public ResponseEntity<String> logout(
@ApiOperation(value = "회원 탈퇴", notes = "회원 탈퇴시 로그아웃이 선행 처리가 되어야함"
+ "따라서 Authroization: Bearer 토큰 제거, Refresh토큰"
+ "Redis에서 제거, HttpOnlyCookie에서 제거 이후 인증 제공자 OAuth2 로그아웃 처리")
@DeleteMapping("/auth/social/{provider}")
@DeleteMapping("/social/{provider}")
public ResponseEntity<String> userWithdrawalUserSelf(
@PathVariable AuthenticationProvider provider,
@AuthenticationPrincipal String socialId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
@RequiredArgsConstructor
public class SocialAuthenticationManager implements AuthenticationManager {


private final SocialLoginStrategy<AuthId> socialLoginStrategy;

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ public class StoreManagerRestController{


@ApiOperation(value = "중복 이메일 체크",notes = "회원가입시 중복 이메일을 체크한다.")
@PostMapping("/api/auth/stores/emails/{email}")
@PostMapping("/stores/emails/{email}")
public ResponseEntity<String> emailDuplicationCheck(@PathVariable String email) {
emailDuplicationCheckerService.isDuplicated(email);
return ResponseEntity.ok("중복 이메일이 아닙니다.");
}

@ApiOperation(value = "회원가입", notes = "회원가입시 이메일 인증을 완료한 스토어 매니저만 회원가입이 가능함")
@PostMapping("/api/auth/stores/signup")
@PostMapping("/stores/signup")
public ResponseEntity<String> signup(@Valid @RequestBody StoreMangerSignUpCommand dto) {
emailDuplicationCheckerService.isDuplicated(dto.getEmail());
Long getSignedUpId = storeManagerService.signUp(dto);
Expand All @@ -53,15 +53,15 @@ public ResponseEntity<String> signup(@Valid @RequestBody StoreMangerSignUpComman

@ApiOperation(value = "스토어 매니저 로그인", notes = "Authroization: Bearer 토큰 생성, Refresh토큰"
+ "Redis에 생성, HttpOnlyCookie에 생성")
@PostMapping("/api/auth/stores/login")
@PostMapping("/stores/login")
public ResponseEntity<StoreManagerLoginResponse> login(@AuthenticationPrincipal AuthId authId) {
String name = storeManagerNameRequest.getName(authId).getName();
return ResponseEntity.ok(StoreManagerMessageMapper.createLoginResponse(name));
}

@ApiOperation(value = "스토어 매니저 로그아웃",notes = "Authroization: Bearer 토큰 제거, Refresh토큰"
+ "Redis에서 제거, HttpOnlyCookie에서 제거")
@PostMapping("/api/auth/stores/logout")
@PostMapping("/stores/logout")
public ResponseEntity<String> logout(@AuthenticationPrincipal AuthId authId) {
storeManagerService.logout(authId);
return ResponseEntity.ok("스토어 매니저 로그아웃 완료");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

Expand All @@ -25,7 +25,7 @@ public class SystemAdminRestController {
+ " ROLE_STORE_MANAGER_PERMITTED,\n"
+ " ROLE_STORE_MANAGER_PENDING,\n"
+ " ROLE_STORE_MANAGER_DENIED")
@PutMapping("/api/auth/admin/store-manager")
@PatchMapping("/admin/store-manager")
public ResponseEntity<String> updateStoreManagerStatus(
@Valid @RequestBody UpdateStoreManagerStatusDto dto) {
updateStoreMangerStatusService.update(dto.getStoreManagerId(), dto.getStatus());
Expand All @@ -34,14 +34,14 @@ public ResponseEntity<String> updateStoreManagerStatus(

@ApiOperation(value = "시스템 관리자 로그인", notes = "Authroization: Bearer 토큰 생성, Refresh토큰"
+ "Redis에 생성, HttpOnlyCookie에 생성")
@PostMapping("/api/auth/admin/login")
@PostMapping("/admin/login")
public ResponseEntity<String> login(){
return ResponseEntity.ok("시스템 관리자 로그인 완료");
}

@ApiOperation(value = "시스템 관리자 로그아웃", notes = "Authroization: Bearer 토큰 제거, Refresh토큰"
+ "Redis에서 제거, HttpOnlyCookie에서 제거")
@PostMapping("/api/auth/admin/logout")
@PostMapping("/admin/logout")
public ResponseEntity<String> logout() {
return ResponseEntity.ok("시스템 관리자 로그아웃 완료");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@

import com.bit.lot.flower.auth.common.security.SecurityContextUtil;
import com.bit.lot.flower.auth.common.util.ExtractAuthorizationTokenUtil;
import com.bit.lot.flower.auth.common.util.JwtUtil;
import com.bit.lot.flower.auth.common.valueobject.Role;
import com.bit.lot.flower.auth.common.valueobject.SecurityPolicyStaticValue;
import io.jsonwebtoken.Claims;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,14 @@ MvcResult setToken() throws Exception {
jwtToken = JwtUtil.generateAccessToken(jwtSubject);
redisToken = JwtUtil.generateRefreshToken(jwtSubject);
redisRefreshTokenUtil.saveRefreshToken(eq(jwtSubject), eq(redisToken), anyLong());
return mvc.perform(MockMvcRequestBuilders.post("/api/auth/admin/logout")
return mvc.perform(MockMvcRequestBuilders.post("/admin/logout")
.header(authorizationHeaderName, authenticationHeaderPrefix + jwtToken))
.andExpect(status().isOk())
.andReturn();
}

void setWithoutTokenAtRequestHeader() throws Exception {
mvc.perform(MockMvcRequestBuilders.post("/api/auth/admin/logout"));
mvc.perform(MockMvcRequestBuilders.post("/admin/logout"));
}

@BeforeEach
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.bit.lot.flower.auth.common.interceptor.refresh;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;

import com.bit.lot.flower.auth.common.http.interceptor.filter.ExceptionHandlerFilter;
import io.jsonwebtoken.ExpiredJwtException;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;


@ExtendWith(MockitoExtension.class)
class GetUserDataWhenTokenIsExpiredTest {

@Mock
ExceptionHandlerFilter exceptionHandlerFilter;
@Mock
HttpServletRequest request;
@Mock
HttpServletResponse response;
@Mock
FilterChain filterChain;

@Test
@DisplayName("JWT 토큰이 Expired 되었을 때 Response에 RenewAccessTokenDto 확인")
void GetUserTokenInfo_WhenTokenIsExpired_ResponseWithRenewAccessTokenDto()
throws ServletException, IOException {
doThrow(ExpiredJwtException.class).when(exceptionHandlerFilter)
.doFilterInternal(any(HttpServletRequest.class), any(HttpServletResponse.class),
any(FilterChain.class));
assertThrowsExactly(ExpiredJwtException.class, () -> {
exceptionHandlerFilter.doFilterInternal(request, response, filterChain);
});

}
}
Loading

0 comments on commit 04b130e

Please sign in to comment.