Skip to content

Commit

Permalink
Merge pull request #16 from TeamMiso/feat/token-reissue
Browse files Browse the repository at this point in the history
토큰 재발급 api 구현
  • Loading branch information
uuuuuuuk authored Oct 11, 2023
2 parents 87dc635 + 12eb75e commit d99613d
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,27 @@ package andreas311.miso.domain.auth.presentation

import andreas311.miso.domain.auth.presentation.data.request.SignInRequestDto
import andreas311.miso.domain.auth.presentation.data.request.SignUpRequestDto
import andreas311.miso.domain.auth.presentation.data.response.NewRefreshTokenResponseDto
import andreas311.miso.domain.auth.presentation.data.response.SignInResponseDto
import andreas311.miso.domain.auth.service.SignInService
import andreas311.miso.domain.auth.service.SignUpService
import andreas311.miso.domain.auth.service.TokenReissueService
import andreas311.miso.domain.auth.util.AuthConverter
import andreas311.miso.global.annotation.RequestController
import org.springframework.http.HttpStatus
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.RequestBody
import org.springframework.web.bind.annotation.RequestHeader
import javax.validation.Valid

@RequestController("/auth")
class AuthController(
private val signUpService: SignUpService,
private val signInService: SignInService,
private val authConverter: AuthConverter
private val authConverter: AuthConverter,
private val tokenReissueService: TokenReissueService
) {

@PostMapping
Expand All @@ -29,4 +34,9 @@ class AuthController(
fun signIn(@Valid @RequestBody signInRequestDto: SignInRequestDto): ResponseEntity<SignInResponseDto> =
authConverter.toDto(signInRequestDto)
.let { ResponseEntity.ok(signInService.execute(it)) }

@PatchMapping
fun getNewRefreshToken(@RequestHeader("Refresh-Token") refreshToken: String): ResponseEntity<NewRefreshTokenResponseDto> =
tokenReissueService.execute(refreshToken)
.let { ResponseEntity.status(HttpStatus.OK).body(it) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package andreas311.miso.domain.auth.presentation.data.response

import com.fasterxml.jackson.annotation.JsonFormat
import java.time.ZonedDateTime

data class NewRefreshTokenResponseDto(
val accessToken: String,
val refreshToken: String,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss")
val accessExp: ZonedDateTime,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss")
val refreshExp: ZonedDateTime
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package andreas311.miso.domain.auth.service

import andreas311.miso.domain.auth.presentation.data.response.NewRefreshTokenResponseDto

interface TokenReissueService {

fun execute(refreshToken: String): NewRefreshTokenResponseDto
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package andreas311.miso.domain.auth.service.impl

import andreas311.miso.domain.auth.presentation.data.response.NewRefreshTokenResponseDto
import andreas311.miso.domain.auth.repository.RefreshTokenRepository
import andreas311.miso.domain.auth.service.TokenReissueService
import andreas311.miso.domain.auth.util.AuthConverter
import andreas311.miso.domain.user.enums.Role
import andreas311.miso.domain.user.exception.UserNotFoundException
import andreas311.miso.domain.user.repository.UserRepository
import andreas311.miso.global.annotation.RollbackService
import andreas311.miso.global.security.exception.TokenExpiredException
import andreas311.miso.global.security.exception.TokenInvalidException
import andreas311.miso.global.security.jwt.TokenProvider
import java.time.ZonedDateTime

@RollbackService
class TokenReissueServiceImpl(
private val authConverter: AuthConverter,
private val tokenProvider: TokenProvider,
private val userRepository: UserRepository,
private val refreshTokenRepository: RefreshTokenRepository,
) : TokenReissueService {

override fun execute(refreshToken: String): NewRefreshTokenResponseDto {
val refresh = tokenProvider.parseToken(refreshToken)
?: throw TokenInvalidException()

val email: String = tokenProvider.exactEmailFromRefreshToken(refresh)

val existingRefreshToken = refreshTokenRepository.findByToken(refresh)
?: throw TokenExpiredException()

val newAccessToken = tokenProvider.generateAccessToken(email)
val newRefreshToken = tokenProvider.generateRefreshToken(email)
val accessExp: ZonedDateTime = tokenProvider.accessExpiredTime
val refreshExp: ZonedDateTime = tokenProvider.refreshExpiredTime

val newRefreshTokenEntity = authConverter.toEntity(
userId = existingRefreshToken.userId,
refreshToken = newRefreshToken
)

refreshTokenRepository.save(newRefreshTokenEntity)
val user = userRepository.findByEmail(email)
?: throw UserNotFoundException()

return NewRefreshTokenResponseDto(
accessToken = newAccessToken,
refreshToken = newRefreshToken,
accessExp = accessExp,
refreshExp = refreshExp
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class SecurityConfig(

.antMatchers(HttpMethod.POST, "/auth").permitAll()
.antMatchers(HttpMethod.POST, "/auth/signIn").permitAll()
.antMatchers(HttpMethod.PATCH, "/auth").permitAll()

.antMatchers(HttpMethod.POST, "/email").permitAll()

Expand Down

0 comments on commit d99613d

Please sign in to comment.