Skip to content

Commit

Permalink
Merge branch 'Feat/#31' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
hyukjinKimm committed Jul 10, 2024
2 parents b0f7312 + 62f29b5 commit cc70097
Show file tree
Hide file tree
Showing 39 changed files with 1,014 additions and 346 deletions.
5 changes: 4 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
buildscript {
ext {
springCloudVersion= "2023.0.2"
springCloudVersion = "2023.0.2"
restdocsApiSpecVersion = '0.17.1'
}
}
Expand Down Expand Up @@ -53,6 +53,9 @@ dependencies {
//Redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis:3.2.1'

// Client Secret 생성 라이브러리
implementation 'com.nimbusds:nimbus-jose-jwt:3.10'

//Api
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,104 +31,103 @@
@Service
public class JwtProviderImpl implements JwtProvider {

private final SecretKey secretKey;
private final RefreshTokenRepository refreshTokenRepository;
private final String JWT_SECRET;

public JwtProviderImpl(@Value("${jwt.secret}") String secret, RefreshTokenRepository refreshTokenRepository) {
this.JWT_SECRET = secret;
this.refreshTokenRepository = refreshTokenRepository;
this.secretKey = Keys.hmacShaKeyFor(JWT_SECRET.getBytes());
}

@Override
public String issueAccessToken(Long userId) {
return generateToken(JwtConstants.ACCESS_TOKEN, userId,
JwtConstants.ACCESS_TOKEN_EXPIRATION_TIME);
}

@Override
public String issueRefreshToken(Long userId) {
String refreshToken = generateToken(JwtConstants.REFRESH_TOKEN, userId,
JwtConstants.REFRESH_TOKEN_EXPIRATION_TIME);
String key = REFRESH_TOKEN_PREFIX + userId;
refreshTokenRepository.saveRefreshToken(userId,refreshToken, JwtConstants.REFRESH_TOKEN_EXPIRATION_TIME);
return refreshToken;
}

public String generateToken(String type, Long userId, Long tokenExpirationTime) {
final Date now = new Date();
final Claims claims = Jwts.claims()
.setIssuedAt(now)
.setExpiration(new Date(now.getTime() + tokenExpirationTime)); // 만료 시간

claims.put(JwtConstants.TOKEN_TYPE, type);
claims.put(JwtConstants.USER_ID, userId);

return Jwts.builder()
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
.setClaims(claims)
.signWith(secretKey)
.compact();
}

@Override
public void validateAccessToken(String accessToken) {
validateToken(accessToken);
}

@Override
public void validateRefreshToken(String refreshToken) {
validateToken(refreshToken);
final Long id = getUserIdFromJwtSubject(refreshToken);
final String key = REFRESH_TOKEN_PREFIX + id;

if (!refreshTokenRepository.hasRefreshToken(key)) {
throw new UnauthorizedException(INVALID_REFRESH_TOKEN);
private final SecretKey secretKey;
private final RefreshTokenRepository refreshTokenRepository;
private final String JWT_SECRET;

public JwtProviderImpl(@Value("${jwt.secret}") String secret, RefreshTokenRepository refreshTokenRepository) {
this.JWT_SECRET = secret;
this.refreshTokenRepository = refreshTokenRepository;
this.secretKey = Keys.hmacShaKeyFor(JWT_SECRET.getBytes());
}
}

@Override
public void equalsRefreshToken(String refreshToken, String savedRefreshToken) {
if(!refreshToken.equals(savedRefreshToken)) {
throw new UnauthorizedException(MISMATCH_REFRESH_TOKEN);
@Override
public String issueAccessToken(Long userId) {
return generateToken(JwtConstants.ACCESS_TOKEN, userId,
JwtConstants.ACCESS_TOKEN_EXPIRATION_TIME);
}
}

public JwtValidationType validateToken(String token) {
try {
final Claims claims = getBodyFromJwt(token);
if (claims.get(JwtConstants.TOKEN_TYPE).toString().equals(JwtConstants.ACCESS_TOKEN)) {
return JwtValidationType.VALID_ACCESS;
} else if (claims.get(JwtConstants.TOKEN_TYPE).toString().equals(JwtConstants.REFRESH_TOKEN)) {
return JwtValidationType.VALID_REFRESH;
}
throw new UnauthorizedException(INVALID_TOKEN);
} catch (MalformedJwtException e) {
throw new UnauthorizedException(INVALID_TOKEN);
} catch (ExpiredJwtException e) {
throw new UnauthorizedException(EXPIRED_TOKEN);
} catch (IllegalArgumentException e) {
throw new UnauthorizedException(UNKNOWN_TOKEN);
} catch (UnsupportedJwtException e) {
throw new UnauthorizedException(UNSUPPORTED_TOKEN);
} catch (SignatureException e) {
throw new UnauthorizedException(WRONG_SIGNATURE_TOKEN);

@Override
public String issueRefreshToken(Long userId) {
String refreshToken = generateToken(JwtConstants.REFRESH_TOKEN, userId,
JwtConstants.REFRESH_TOKEN_EXPIRATION_TIME);
refreshTokenRepository.saveRefreshToken(userId, refreshToken, JwtConstants.REFRESH_TOKEN_EXPIRATION_TIME);
return refreshToken;
}

public String generateToken(String type, Long userId, Long tokenExpirationTime) {
final Date now = new Date();
final Claims claims = Jwts.claims()
.setIssuedAt(now)
.setExpiration(new Date(now.getTime() + tokenExpirationTime)); // 만료 시간

claims.put(JwtConstants.TOKEN_TYPE, type);
claims.put(JwtConstants.USER_ID, userId);

return Jwts.builder()
.setHeaderParam(Header.TYPE, Header.JWT_TYPE)
.setClaims(claims)
.signWith(secretKey)
.compact();
}

@Override
public void validateAccessToken(String accessToken) {
validateToken(accessToken);
}

@Override
public void validateRefreshToken(String refreshToken) {
validateToken(refreshToken);
final Long id = getUserIdFromJwtSubject(refreshToken);
final String key = REFRESH_TOKEN_PREFIX + id;

if (!refreshTokenRepository.hasRefreshToken(key)) {
throw new UnauthorizedException(INVALID_REFRESH_TOKEN);
}
}

@Override
public void equalsRefreshToken(String refreshToken, String savedRefreshToken) {
if (!refreshToken.equals(savedRefreshToken)) {
throw new UnauthorizedException(MISMATCH_REFRESH_TOKEN);
}
}

public JwtValidationType validateToken(String token) {
try {
final Claims claims = getBodyFromJwt(token);
if (claims.get(JwtConstants.TOKEN_TYPE).toString().equals(JwtConstants.ACCESS_TOKEN)) {
return JwtValidationType.VALID_ACCESS;
} else if (claims.get(JwtConstants.TOKEN_TYPE).toString().equals(JwtConstants.REFRESH_TOKEN)) {
return JwtValidationType.VALID_REFRESH;
}
throw new UnauthorizedException(INVALID_TOKEN);
} catch (MalformedJwtException e) {
throw new UnauthorizedException(INVALID_TOKEN);
} catch (ExpiredJwtException e) {
throw new UnauthorizedException(EXPIRED_TOKEN);
} catch (IllegalArgumentException e) {
throw new UnauthorizedException(UNKNOWN_TOKEN);
} catch (UnsupportedJwtException e) {
throw new UnauthorizedException(UNSUPPORTED_TOKEN);
} catch (SignatureException e) {
throw new UnauthorizedException(WRONG_SIGNATURE_TOKEN);
}
}

public Long getUserIdFromJwtSubject(String token) {
Claims claims = getBodyFromJwt(token);
return claims.get(JwtConstants.USER_ID, Long.class);
}

private Claims getBodyFromJwt(String token) {
JwtParser parser = getJwtParser();
return parser.parseClaimsJws(token).getBody();
}

private JwtParser getJwtParser() {
return Jwts.parserBuilder()
.setSigningKey(secretKey).build();
}
}

public Long getUserIdFromJwtSubject(String token) {
Claims claims = getBodyFromJwt(token);
return claims.get(JwtConstants.USER_ID, Long.class);
}

private Claims getBodyFromJwt(String token) {
JwtParser parser = getJwtParser();
return parser.parseClaimsJws(token).getBody();
}

private JwtParser getJwtParser(){
return Jwts.parserBuilder()
.setSigningKey(secretKey).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

import static com.donkeys_today.server.support.jwt.JwtConstants.REFRESH_TOKEN_EXPIRATION_TIME;

import com.donkeys_today.server.application.user.sterategy.AppleAuthStrategy;
import com.donkeys_today.server.application.user.sterategy.GoogleAuthStrategy;
import com.donkeys_today.server.application.user.sterategy.KakaoAuthStrategy;
import com.donkeys_today.server.application.user.sterategy.SocialRegisterSterategy;
import com.donkeys_today.server.domain.user.Platform;
import com.donkeys_today.server.domain.user.User;
import com.donkeys_today.server.presentation.user.dto.requset.UserSignInRequest;
import com.donkeys_today.server.presentation.user.dto.requset.UserSignUpRequest;
import com.donkeys_today.server.support.jwt.JwtProvider;
import com.donkeys_today.server.support.jwt.RefreshTokenRepository;
import com.donkeys_today.server.support.jwt.Token;
Expand All @@ -20,41 +24,50 @@
@RequiredArgsConstructor
public class UserAuthenticator {

private final Map<Platform, SocialRegisterSterategy> provider = new HashMap<>();
private final Map<Platform, SocialRegisterSterategy> provider = new HashMap<>();

private final KakaoAuthStrategy kakaoAuthStrategy;
private final JwtProvider jwtProvider;
private final RefreshTokenRepository refreshTokenRepository;
private final KakaoAuthStrategy kakaoAuthStrategy;
private final GoogleAuthStrategy googleAuthStrategy;
private final AppleAuthStrategy appleAuthStrategy;
private final JwtProvider jwtProvider;
private final RefreshTokenRepository refreshTokenRepository;

@PostConstruct
public void initSocialLoginProvider() {
provider.put(Platform.KAKAO, kakaoAuthStrategy);
}
@PostConstruct
public void initSocialLoginProvider() {
provider.put(Platform.KAKAO, kakaoAuthStrategy);
provider.put(Platform.GOOGLE, googleAuthStrategy);
provider.put(Platform.APPLE, appleAuthStrategy);
}

public User signUp(String authToken, Platform platform) {
return provider.get(platform).signUp(platform, authToken);
}
public User signUp(String authToken, UserSignUpRequest request) {
Platform platform = getPlatformFromRequestString(request.platform());
return provider.get(platform).signUp(request, authToken);
}

public User signIn(String authToken, Platform platform) {
return provider.get(platform).signIn(platform, authToken);
}
public User signIn(String authToken, UserSignInRequest request) {
Platform platform = getPlatformFromRequestString(request.platform());
return provider.get(platform).signIn(request, authToken);
}

public void setUserAlarm(User user, boolean agreement, LocalTime localTime) {
if (agreement) {
user.updateUserAlarmAgreement(true);
//TODO 해당 부분은 와이어프레임에 따라서, 온보딩 과정에서 알람을 설정할지, 아니면 따로 설정할 지 정해지는 것 보고 구현
public void setUserAlarm(User user, boolean agreement, LocalTime localTime) {
if (agreement) {
user.updateUserAlarmAgreement(true);
//TODO 해당 부분은 와이어프레임에 따라서, 온보딩 과정에서 알람을 설정할지, 아니면 따로 설정할 지 정해지는 것 보고 구현
}
}
}

public Token issueToken(Long id) {
String accessToken = jwtProvider.issueAccessToken(id);
String refreshToken = jwtProvider.issueRefreshToken(id);
storeRefreshToken(id, refreshToken);
return Token.of(accessToken, refreshToken);
}
public Token issueToken(Long id) {
String accessToken = jwtProvider.issueAccessToken(id);
String refreshToken = jwtProvider.issueRefreshToken(id);
storeRefreshToken(id, refreshToken);
return Token.of(accessToken, refreshToken);
}

private void storeRefreshToken(Long id, String refreshToken) {
refreshTokenRepository.saveRefreshToken(id, refreshToken, REFRESH_TOKEN_EXPIRATION_TIME);
}
private void storeRefreshToken(Long id, String refreshToken) {
refreshTokenRepository.saveRefreshToken(id, refreshToken, REFRESH_TOKEN_EXPIRATION_TIME);
}

private Platform getPlatformFromRequestString(String platform) {
return Platform.fromString(platform);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,40 +18,38 @@
@RequiredArgsConstructor
public class UserService {

private final UserRepository userRepository;
private final UserRetriever userRetriever;
private final UserAuthenticator userAuthenticator;
private final UserUpdater userUpdater;
private final UserRemover userRemover;

private final RefreshTokenRepository refreshTokenRepository;
private final JwtProvider jwtProvider;

@Transactional
public UserSignUpResponse signUp(final String authorizationCode,
final UserSignUpRequest request) {
//플랫폼에서 플랫폼 추출해야 함
//그래서 해당 플랫폼에다가 유저 생성 기능 위임
Platform platform = getPlatformFromRequestString(request.platform());
User newUser= userAuthenticator.signUp(authorizationCode, platform);
User savedUser = userRepository.save(newUser);
//알람 설정했을 경우, 알람 설정 (이벤트 분리)
userAuthenticator.setUserAlarm(savedUser,request.alarmAgreement(),request.alarmTime());
//토큰 생성하고 redis에 저장.
Token token = userAuthenticator.issueToken(savedUser.getId());
return UserSignUpResponse.of(savedUser.getId(), token.accessToken(),token.refreshToken());
}

public UserSignInResponse signIn(final String authorizationCode,
final UserSignInRequest request){

Platform platform = getPlatformFromRequestString(request.platform());
User foundUser = userAuthenticator.signIn(authorizationCode,platform);
Token token = userAuthenticator.issueToken(foundUser.getId());
return UserSignInResponse.of(foundUser.getId(), token.accessToken(),token.refreshToken());
}

private Platform getPlatformFromRequestString(String request) {
return Platform.fromString(request);
}
private final UserRepository userRepository;
private final UserRetriever userRetriever;
private final UserAuthenticator userAuthenticator;
private final UserUpdater userUpdater;
private final UserRemover userRemover;

private final RefreshTokenRepository refreshTokenRepository;
private final JwtProvider jwtProvider;

@Transactional
public UserSignUpResponse signUp(final String authorizationCode,
final UserSignUpRequest request) {
//플랫폼에서 플랫폼 추출해야 함
//그래서 해당 플랫폼에다가 유저 생성 기능 위임
User newUser = userAuthenticator.signUp(authorizationCode, request);
User savedUser = userRepository.save(newUser);
//알람 설정했을 경우, 알람 설정 (이벤트 분리)
// userAuthenticator.setUserAlarm(savedUser,request.alarmAgreement(),request.alarmTime());
//토큰 생성하고 redis에 저장.
Token token = userAuthenticator.issueToken(savedUser.getId());
return UserSignUpResponse.of(savedUser.getId(), token.accessToken(), token.refreshToken());
}

public UserSignInResponse signIn(final String authorizationCode,
final UserSignInRequest request) {

User foundUser = userAuthenticator.signIn(authorizationCode, request);
Token token = userAuthenticator.issueToken(foundUser.getId());
return UserSignInResponse.of(foundUser.getId(), token.accessToken(), token.refreshToken());
}

private Platform getPlatformFromRequestString(String request) {
return Platform.fromString(request);
}
}
Loading

0 comments on commit cc70097

Please sign in to comment.