Skip to content

Commit

Permalink
Merge pull request #8 from GSM-MSG/feature/7-reissue-token
Browse files Browse the repository at this point in the history
๐Ÿ”€ ํ† ํฐ ์žฌ๋ฐœ๊ธ‰
  • Loading branch information
ta2ye0n authored Nov 1, 2024
2 parents e0457b8 + ebbcf15 commit c2821f7
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.gcms.v3.domain.auth.domain.entity;

import lombok.Builder;
import lombok.Getter;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
import org.springframework.data.redis.core.index.Indexed;

@Getter
@Builder
@RedisHash(value = "refreshToken", timeToLive = 60L * 60 * 24 * 7)
public class RefreshToken {

@Indexed
private String email;

@Id
@Indexed
private String token;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.gcms.v3.domain.auth.domain.repository;

import com.gcms.v3.domain.auth.domain.entity.RefreshToken;
import org.springframework.data.repository.CrudRepository;

import java.util.Optional;

public interface RefreshTokenRepository extends CrudRepository<RefreshToken, String> {
Optional<RefreshToken> findByToken(String token);

RefreshToken findByEmail(String email);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.gcms.v3.domain.auth.exception;

import com.gcms.v3.global.error.BasicException;
import com.gcms.v3.global.error.ErrorCode;

public class ExpiredTokenException extends BasicException {
public ExpiredTokenException() {
super(ErrorCode.EXPIRED_TOKEN);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.gcms.v3.domain.auth.presentation.data.request.SignInRequestDto;
import com.gcms.v3.domain.auth.presentation.data.response.TokenInfoResponseDto;
import com.gcms.v3.domain.auth.service.ReissueTokenService;
import com.gcms.v3.domain.auth.service.SignInService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
Expand All @@ -13,10 +14,17 @@
public class AuthController {

private final SignInService signInService;
private final ReissueTokenService reissueTokenService;

@PostMapping
public ResponseEntity<TokenInfoResponseDto> signIn (@RequestBody SignInRequestDto signInRequestDto) {
TokenInfoResponseDto res = signInService.execute(signInRequestDto);
return ResponseEntity.ok(res);
}

@PostMapping("/reissueToken")
public ResponseEntity<TokenInfoResponseDto> reissueToken (@RequestBody String refreshToken) {
TokenInfoResponseDto res = reissueTokenService.execute(refreshToken);
return ResponseEntity.ok(res);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.gcms.v3.domain.auth.service;

import com.gcms.v3.domain.auth.presentation.data.response.TokenInfoResponseDto;

public interface ReissueTokenService {
TokenInfoResponseDto execute(String refreshToken);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.gcms.v3.domain.auth.service.impl;

import com.gcms.v3.domain.auth.domain.entity.RefreshToken;
import com.gcms.v3.domain.auth.domain.repository.RefreshTokenRepository;
import com.gcms.v3.domain.auth.exception.UserNotFoundException;
import com.gcms.v3.domain.auth.presentation.data.response.TokenInfoResponseDto;
import com.gcms.v3.domain.auth.service.ReissueTokenService;
import com.gcms.v3.domain.user.domain.entity.User;
import com.gcms.v3.domain.user.domain.repository.UserRepository;
import com.gcms.v3.global.security.exception.ExpiredTokenException;
import com.gcms.v3.global.security.jwt.JwtTokenProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class ReissueTokenServiceImpl implements ReissueTokenService {

private final JwtTokenProvider jwtTokenProvider;
private final UserRepository userRepository;
private final RefreshTokenRepository refreshTokenRepository;

public TokenInfoResponseDto execute(String refreshToken) {
String refresh = jwtTokenProvider.parseToken(refreshToken);

String email = jwtTokenProvider.exactEmailFromRefreshToken(refresh);

User user = userRepository.findByEmail(email)
.orElseThrow(UserNotFoundException::new);

RefreshToken existingRefreshToken = refreshTokenRepository.findByToken(refresh)
.orElseThrow(ExpiredTokenException::new);

TokenInfoResponseDto responseDto = jwtTokenProvider.generateToken(user.getEmail());

saveRefreshToken(existingRefreshToken.getEmail(), responseDto.refreshToken());

return responseDto;
}

private void saveRefreshToken(String email, String refreshToken) {
RefreshToken token = RefreshToken.builder()
.email(email)
.token(refreshToken)
.build();

refreshTokenRepository.save(token);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.gcms.v3.domain.auth.service.impl;

import com.gcms.v3.domain.auth.domain.entity.RefreshToken;
import com.gcms.v3.domain.auth.domain.repository.RefreshTokenRepository;
import com.gcms.v3.domain.auth.presentation.data.request.SignInRequestDto;
import com.gcms.v3.domain.auth.presentation.data.response.TokenInfoResponseDto;
import com.gcms.v3.domain.auth.service.SignInService;
Expand All @@ -24,6 +26,7 @@ public class SignInServiceImpl implements SignInService {
private final UserRepository userRepository;
private final JwtTokenProvider jwtTokenProvider;
private final UserRoleRepository userRoleRepository;
private final RefreshTokenRepository refreshTokenRepository;

public TokenInfoResponseDto execute(SignInRequestDto signInRequestDto) {
String accessToken = oAuth2Service.requestAccessToken(signInRequestDto.code());
Expand All @@ -32,7 +35,11 @@ public TokenInfoResponseDto execute(SignInRequestDto signInRequestDto) {
User user = userRepository.findByEmail(googleOAuth2UserInfo.getEmail())
.orElseGet(() -> toEntity(googleOAuth2UserInfo));

return jwtTokenProvider.generateToken(user.getEmail());
TokenInfoResponseDto responseDto = jwtTokenProvider.generateToken(user.getEmail());

saveRefreshToken(user.getEmail(), responseDto.refreshToken());

return responseDto;
}

private User toEntity(GoogleOAuth2UserInfo googleOAuth2UserInfo) {
Expand All @@ -55,4 +62,12 @@ private void saveAuthority(User user) {
userRoleRepository.save(userRole);
}

private void saveRefreshToken(String email, String refreshToken) {
RefreshToken token = RefreshToken.builder()
.email(email)
.token(refreshToken)
.build();

refreshTokenRepository.save(token);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.authorizeHttpRequests((authorizeRequests) ->
authorizeRequests
.requestMatchers(HttpMethod.POST, "/v3/auth").permitAll()
.requestMatchers(HttpMethod.POST, "/v3/auth/reissueToken").authenticated()
)

.addFilterBefore(new ExceptionFilter(objectMapper), UsernamePasswordAuthenticationFilter.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,26 @@ public boolean validateToken(String token) {
}
}

public String parseToken(String token) {
if (token.startsWith(TOKEN_PREFIX)) {
return token.replace(TOKEN_PREFIX, "");
}
else return null;
}

public String exactEmailFromRefreshToken(String refreshToken) {
return getTokenSubject(refreshToken, refreshtokenkey);
}

private String getTokenSubject (String token, Key secret) {
return getTokenBody(token, secret).getSubject();
}

private Claims getTokenBody(String token, Key secret) {
return Jwts.parserBuilder()
.setSigningKey(secret)
.build()
.parseClaimsJws(token)
.getBody();
}
}

0 comments on commit c2821f7

Please sign in to comment.