-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: kssumin <[email protected]>
- Loading branch information
Showing
23 changed files
with
509 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
src/main/java/com/kakao/golajuma/auth/domain/exception/NotFoundException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.kakao.golajuma.auth.domain.exception; | ||
|
||
import com.kakao.golajuma.common.exception.BusinessException; | ||
import org.springframework.http.HttpStatus; | ||
|
||
public class NotFoundException extends BusinessException { | ||
|
||
public NotFoundException(String message) { | ||
super(message, HttpStatus.NOT_FOUND); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
src/main/java/com/kakao/golajuma/auth/domain/exception/NotValidToken.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.kakao.golajuma.auth.domain.exception; | ||
|
||
import com.kakao.golajuma.common.exception.BusinessException; | ||
import org.springframework.http.HttpStatus; | ||
|
||
public class NotValidToken extends BusinessException { | ||
|
||
public NotValidToken(String message) { | ||
super(message, HttpStatus.BAD_REQUEST); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/main/java/com/kakao/golajuma/auth/domain/model/RefreshToken.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.kakao.golajuma.auth.domain.model; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.ToString; | ||
|
||
@Getter | ||
@ToString | ||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
@Builder(toBuilder = true) | ||
public class RefreshToken { | ||
private String refreshToken; | ||
private Long userId; | ||
} |
55 changes: 55 additions & 0 deletions
55
src/main/java/com/kakao/golajuma/auth/domain/service/LoginUserService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package com.kakao.golajuma.auth.domain.service; | ||
|
||
import com.kakao.golajuma.auth.domain.exception.NotFoundException; | ||
import com.kakao.golajuma.auth.domain.token.TokenProvider; | ||
import com.kakao.golajuma.auth.domain.token.TokenResolver; | ||
import com.kakao.golajuma.auth.infra.entity.UserEntity; | ||
import com.kakao.golajuma.auth.infra.repository.UserRepository; | ||
import com.kakao.golajuma.auth.web.dto.converter.TokenConverter; | ||
import com.kakao.golajuma.auth.web.dto.request.LoginUserRequest; | ||
import com.kakao.golajuma.auth.web.dto.response.TokenResponse; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.security.crypto.password.PasswordEncoder; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional(readOnly = true) | ||
public class LoginUserService { | ||
|
||
private final TokenProvider tokenProvider; | ||
private final UserRepository userRepository; | ||
private final PasswordEncoder passwordEncoder; | ||
private final TokenConverter tokenConverter; | ||
private final TokenResolver tokenResolver; | ||
private final TokenService tokenService; | ||
|
||
@Transactional | ||
public TokenResponse execute(final LoginUserRequest request) { | ||
UserEntity userEntity = | ||
userRepository | ||
.findByEmail(request.getEmail()) | ||
.orElseThrow(() -> new NotFoundException("존재하지 않는 이메일입니다.")); | ||
|
||
validPassword(request.getPassword(), userEntity); | ||
|
||
String accessToken = tokenProvider.createAccessToken(userEntity.getId()); | ||
String refreshToken = tokenProvider.createRefreshToken(userEntity.getId()); | ||
|
||
tokenService.execute(userEntity.getId(), refreshToken); | ||
|
||
return tokenConverter.from( | ||
accessToken, tokenResolver.getExpiredDate(accessToken), refreshToken); | ||
} | ||
|
||
private void validPassword(final String requestPassword, final UserEntity userEntity) { | ||
if (!matchPassword(requestPassword, userEntity.getPassword())) { | ||
throw new NotFoundException("존재하지 않는 비밀번호입니다"); | ||
} | ||
} | ||
|
||
private boolean matchPassword(final String requestPassword, final String password) { | ||
return passwordEncoder.matches(requestPassword, password); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/com/kakao/golajuma/auth/domain/service/TokenService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.kakao.golajuma.auth.domain.service; | ||
|
||
import com.kakao.golajuma.auth.domain.model.RefreshToken; | ||
import com.kakao.golajuma.auth.infra.repository.RefreshTokenRepository; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class TokenService { | ||
private final RefreshTokenRepository refreshTokenRepository; | ||
|
||
@Transactional | ||
public void execute(Long userId, String token) { | ||
RefreshToken refreshToken = RefreshToken.builder().refreshToken(token).userId(userId).build(); | ||
refreshTokenRepository.save(refreshToken); | ||
} | ||
} |
54 changes: 54 additions & 0 deletions
54
src/main/java/com/kakao/golajuma/auth/domain/token/TokenProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.kakao.golajuma.auth.domain.token; | ||
|
||
import io.jsonwebtoken.Header; | ||
import io.jsonwebtoken.Jwts; | ||
import io.jsonwebtoken.security.Keys; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Date; | ||
import javax.crypto.SecretKey; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
public class TokenProvider { | ||
|
||
private static final String USER_ID_CLAIM_KEY = "memberId"; | ||
private static final String USER_ROLE_CLAIM_KEY = "memberRole"; | ||
private final SecretKey accessSecretKey; | ||
|
||
private final long accessValidTime; | ||
private final SecretKey refreshSecretKey; | ||
|
||
private final long refreshValidTime; | ||
|
||
public TokenProvider( | ||
@Value("${security.jwt.token.access.secretKey}") String accessSecretKey, | ||
@Value("${security.jwt.token.access.validTime}") long accessValidTime, | ||
@Value("${security.jwt.token.refresh.secretKey}") String refreshSecretKey, | ||
@Value("${security.jwt.token.refresh.validTime}") long refreshValidTime) { | ||
this.accessSecretKey = Keys.hmacShaKeyFor(accessSecretKey.getBytes(StandardCharsets.UTF_8)); | ||
this.accessValidTime = accessValidTime; | ||
this.refreshSecretKey = Keys.hmacShaKeyFor(refreshSecretKey.getBytes(StandardCharsets.UTF_8)); | ||
this.refreshValidTime = refreshValidTime; | ||
} | ||
|
||
private String createToken(final Long userId, final SecretKey secretKey, final long validTime) { | ||
final Date now = new Date(); | ||
|
||
return Jwts.builder() | ||
.setHeaderParam(Header.TYPE, Header.JWT_TYPE) | ||
.claim(USER_ID_CLAIM_KEY, userId) | ||
.setIssuedAt(now) | ||
.setExpiration(new Date(now.getTime() + validTime)) | ||
.signWith(secretKey) | ||
.compact(); | ||
} | ||
|
||
public String createAccessToken(final Long userId) { | ||
return createToken(userId, accessSecretKey, accessValidTime); | ||
} | ||
|
||
public String createRefreshToken(final Long userId) { | ||
return createToken(userId, refreshSecretKey, refreshValidTime); | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
src/main/java/com/kakao/golajuma/auth/domain/token/TokenResolver.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package com.kakao.golajuma.auth.domain.token; | ||
|
||
import com.kakao.golajuma.auth.domain.exception.NotValidToken; | ||
import io.jsonwebtoken.Claims; | ||
import io.jsonwebtoken.Jwts; | ||
import io.jsonwebtoken.security.Keys; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.Date; | ||
import javax.crypto.SecretKey; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
public class TokenResolver { | ||
|
||
private static final String USER_ID_CLAIM_KEY = "memberId"; | ||
private static final String USER_ROLE_CLAIM_KEY = "memberRole"; | ||
private final SecretKey accessSecretKey; | ||
private final SecretKey refreshSecretKey; | ||
|
||
public TokenResolver( | ||
@Value("${security.jwt.token.access.secretKey}") String accessSecretKey, | ||
@Value("${security.jwt.token.refresh.secretKey}") String refreshSecretKey) { | ||
this.accessSecretKey = Keys.hmacShaKeyFor(accessSecretKey.getBytes(StandardCharsets.UTF_8)); | ||
this.refreshSecretKey = Keys.hmacShaKeyFor(refreshSecretKey.getBytes(StandardCharsets.UTF_8)); | ||
} | ||
|
||
private Claims getClaims(final String token) { | ||
try { | ||
return Jwts.parserBuilder() | ||
.setSigningKey(accessSecretKey) | ||
.build() | ||
.parseClaimsJws(token) | ||
.getBody(); | ||
} catch (Exception e) { | ||
throw new NotValidToken("유효하지 않은 토큰입니다."); | ||
} | ||
} | ||
|
||
public Date getExpiredDate(final String token) { | ||
return getClaims(token).getExpiration(); | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
src/main/java/com/kakao/golajuma/auth/infra/repository/RefreshTokenRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.kakao.golajuma.auth.infra.repository; | ||
|
||
import com.kakao.golajuma.auth.domain.model.RefreshToken; | ||
import java.util.Objects; | ||
import java.util.Optional; | ||
import java.util.concurrent.TimeUnit; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.data.redis.core.RedisTemplate; | ||
import org.springframework.data.redis.core.ValueOperations; | ||
import org.springframework.stereotype.Repository; | ||
|
||
@Repository | ||
@Slf4j | ||
public class RefreshTokenRepository { | ||
|
||
private RedisTemplate<Long, String> redisTemplate; | ||
|
||
@Value("${redis.timeToLive}") | ||
private long ttl; | ||
|
||
public RefreshTokenRepository(final RedisTemplate redisTemplate) { | ||
this.redisTemplate = redisTemplate; | ||
} | ||
|
||
public void save(final RefreshToken refreshToken) { | ||
ValueOperations<Long, String> valueOperations = redisTemplate.opsForValue(); | ||
valueOperations.set(refreshToken.getUserId(), refreshToken.getRefreshToken()); | ||
redisTemplate.expire(refreshToken.getUserId(), ttl, TimeUnit.SECONDS); | ||
} | ||
|
||
public Optional<RefreshToken> findById(final Long userId) { | ||
ValueOperations<Long, String> valueOperations = redisTemplate.opsForValue(); | ||
String refreshToken = valueOperations.get(userId); | ||
|
||
if (Objects.isNull(refreshToken)) { | ||
return Optional.empty(); | ||
} | ||
|
||
return Optional.of(new RefreshToken(refreshToken, userId)); | ||
} | ||
} |
3 changes: 3 additions & 0 deletions
3
src/main/java/com/kakao/golajuma/auth/infra/repository/UserRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,13 @@ | ||
package com.kakao.golajuma.auth.infra.repository; | ||
|
||
import com.kakao.golajuma.auth.infra.entity.UserEntity; | ||
import java.util.Optional; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface UserRepository extends JpaRepository<UserEntity, Long> { | ||
boolean existsByEmail(String email); | ||
|
||
boolean existsByNickname(String nickname); | ||
|
||
Optional<UserEntity> findByEmail(String email); | ||
} |
45 changes: 45 additions & 0 deletions
45
src/main/java/com/kakao/golajuma/auth/web/controller/LoginController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package com.kakao.golajuma.auth.web.controller; | ||
|
||
import com.kakao.golajuma.auth.domain.service.LoginUserService; | ||
import com.kakao.golajuma.auth.web.dto.request.LoginUserRequest; | ||
import com.kakao.golajuma.auth.web.dto.response.TokenResponse; | ||
import com.kakao.golajuma.common.support.respnose.ApiResponse; | ||
import com.kakao.golajuma.common.support.respnose.ApiResponseBody.SuccessBody; | ||
import com.kakao.golajuma.common.support.respnose.ApiResponseGenerator; | ||
import com.kakao.golajuma.common.support.respnose.MessageCode; | ||
import javax.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseCookie; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@RequiredArgsConstructor | ||
@RequestMapping("/api/auth") | ||
public class LoginController { | ||
private static final String REFRESH_TOKEN = "refreshToken"; | ||
private static final int REFRESH_TOKEN_EXPIRATION = 7 * 24 * 60 * 60; | ||
private final LoginUserService loginUserUseCase; | ||
|
||
@PostMapping("/login") | ||
public ApiResponse<SuccessBody<TokenResponse>> signIn( | ||
@RequestBody @Valid LoginUserRequest request) { | ||
final TokenResponse tokenResponse = loginUserUseCase.execute(request); | ||
final ResponseCookie cookie = putTokenInCookie(tokenResponse); | ||
return ApiResponseGenerator.success( | ||
tokenResponse, HttpStatus.OK, MessageCode.CREATE, cookie.toString()); | ||
} | ||
|
||
private ResponseCookie putTokenInCookie(final TokenResponse tokenResponse) { | ||
return ResponseCookie.from(REFRESH_TOKEN, tokenResponse.getRefreshToken()) | ||
.maxAge(REFRESH_TOKEN_EXPIRATION) | ||
.path("/") | ||
.sameSite("None") | ||
.secure(true) | ||
.httpOnly(true) | ||
.build(); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/com/kakao/golajuma/auth/web/dto/converter/TokenConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.kakao.golajuma.auth.web.dto.converter; | ||
|
||
import com.kakao.golajuma.auth.web.dto.response.TokenResponse; | ||
import java.util.Date; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Component; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class TokenConverter { | ||
|
||
public TokenResponse from(String accessToken, Date expiredTime, String refreshToken) { | ||
return TokenResponse.builder() | ||
.accessToken(accessToken) | ||
.expiredTime(expiredTime) | ||
.refreshToken(refreshToken) | ||
.build(); | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
src/main/java/com/kakao/golajuma/auth/web/dto/request/LoginUserRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.kakao.golajuma.auth.web.dto.request; | ||
|
||
import com.kakao.golajuma.auth.web.supplier.EmailSupplier; | ||
import com.kakao.golajuma.common.marker.AbstractRequestDto; | ||
import javax.validation.constraints.Email; | ||
import javax.validation.constraints.NotNull; | ||
import javax.validation.constraints.Size; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
|
||
@Getter | ||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
@Builder(toBuilder = true) | ||
public class LoginUserRequest implements AbstractRequestDto, EmailSupplier { | ||
|
||
@NotNull @Email private String email; | ||
|
||
@NotNull | ||
@Size(min = 8) | ||
private String password; | ||
} |
Oops, something went wrong.