diff --git a/.docker/Dockerfile b/.docker/Dockerfile index b52efd1..707f3c1 100644 --- a/.docker/Dockerfile +++ b/.docker/Dockerfile @@ -7,6 +7,7 @@ SPRING_DATASOURCE_USERNAME=${SPRING_DATASOURCE_USERNAME} \ SPRING_DATASOURCE_PASSWORD=${SPRING_DATASOURCE_PASSWORD} \ GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID} \ GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET} \ +GOOGLE_REDIRECT_URI=${GOOGLE_REDIRECT_URI} \ JWT_SECRET_KEY=${JWT_SECRET_KEY} \ REDIS_HOST=${REDIS_HOST} \ REDIS_PORT=${REDIS_PORT} diff --git a/.docker/docker-compose.yml b/.docker/docker-compose.yml index 05d4495..7d1b90a 100644 --- a/.docker/docker-compose.yml +++ b/.docker/docker-compose.yml @@ -18,6 +18,7 @@ services: SPRING_DATASOURCE_PASSWORD: ${SPRING_DATASOURCE_PASSWORD} GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID} GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET} + GOOGLE_REDIRECT_URI: ${GOOGLE_REDIRECT_URI} JWT_SECRET_KEY: ${JWT_SECRET_KEY} REDIS_HOST: ${REDIS_HOST} REDIS_PORT: ${REDIS_PORT} @@ -34,6 +35,7 @@ services: SPRING_DATASOURCE_PASSWORD: ${SPRING_DATASOURCE_PASSWORD} GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID} GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET} + GOOGLE_REDIRECT_URI: ${GOOGLE_REDIRECT_URI} JWT_SECRET_KEY: ${JWT_SECRET_KEY} REDIS_HOST: ${REDIS_HOST} REDIS_PORT: ${REDIS_PORT} \ No newline at end of file diff --git a/src/main/java/com/dnd/gooding/domain/user/controller/response/UserProfileResponse.java b/src/main/java/com/dnd/gooding/domain/user/controller/response/UserProfileResponse.java index dcba499..da2c47b 100644 --- a/src/main/java/com/dnd/gooding/domain/user/controller/response/UserProfileResponse.java +++ b/src/main/java/com/dnd/gooding/domain/user/controller/response/UserProfileResponse.java @@ -8,7 +8,7 @@ @Builder @Schema(description = "사용자 프로필") public record UserProfileResponse( - @Schema(description = "사용자 순번") + @Schema(description = "사용자 ID") Long id, @Schema(description = "사용자 닉네임") String nickname, diff --git a/src/main/java/com/dnd/gooding/global/config/docs/SwaggerConfiguration.java b/src/main/java/com/dnd/gooding/global/config/docs/SwaggerConfiguration.java index d76bf46..f22e9b2 100644 --- a/src/main/java/com/dnd/gooding/global/config/docs/SwaggerConfiguration.java +++ b/src/main/java/com/dnd/gooding/global/config/docs/SwaggerConfiguration.java @@ -51,4 +51,11 @@ public GroupedOpenApi userGroup() { .pathsToMatch("/api/v1/user/**") .build(); } + + @Bean GroupedOpenApi tokenGroup() { + return GroupedOpenApi.builder() + .group("Token") + .pathsToMatch("/api/v1/tokens/**") + .build(); + } } diff --git a/src/main/java/com/dnd/gooding/global/config/security/SecurityConfiguration.java b/src/main/java/com/dnd/gooding/global/config/security/SecurityConfiguration.java index 9895e1c..ce714fe 100644 --- a/src/main/java/com/dnd/gooding/global/config/security/SecurityConfiguration.java +++ b/src/main/java/com/dnd/gooding/global/config/security/SecurityConfiguration.java @@ -52,6 +52,7 @@ public SecurityFilterChain httpSecurity(HttpSecurity http) throws Exception { .authorizeHttpRequests() .antMatchers("/").permitAll() .antMatchers("/health-check").permitAll() + .antMatchers("/api/v1/tokens/temp").permitAll() .anyRequest().authenticated() .and() .httpBasic().disable() diff --git a/src/main/java/com/dnd/gooding/global/controller/HealthCheckController.java b/src/main/java/com/dnd/gooding/global/controller/HealthCheckController.java index b3136c2..a8c4d53 100644 --- a/src/main/java/com/dnd/gooding/global/controller/HealthCheckController.java +++ b/src/main/java/com/dnd/gooding/global/controller/HealthCheckController.java @@ -3,14 +3,11 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; -import io.swagger.v3.oas.annotations.tags.Tag; - -@Tag(name = "헬스체크", description = "was가 작동하고 있는지 확인합니다.") @RestController public class HealthCheckController { @GetMapping("/health-check") public String healthCheck() { - return "health_check"; + return "health-check"; } } diff --git a/src/main/java/com/dnd/gooding/global/token/api/TokenController.java b/src/main/java/com/dnd/gooding/global/token/api/TokenController.java index add8eb4..c2ea96c 100644 --- a/src/main/java/com/dnd/gooding/global/token/api/TokenController.java +++ b/src/main/java/com/dnd/gooding/global/token/api/TokenController.java @@ -2,20 +2,30 @@ import static org.springframework.http.HttpHeaders.*; +import org.springframework.http.MediaType; import org.springframework.http.ResponseCookie; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import com.dnd.gooding.global.dto.ErrorResponse; import com.dnd.gooding.global.token.api.response.TokenResponse; import com.dnd.gooding.global.token.service.TokenService; import com.dnd.gooding.global.util.CookieUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirements; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +@Tag(name = "Token", description = "토큰 API") @RestController @RequiredArgsConstructor @RequestMapping("/api/v1/tokens") @@ -23,17 +33,41 @@ public class TokenController { private final TokenService tokenService; - @PostMapping + @Operation(summary = "임시 토큰을 발급 받는다.") + @SecurityRequirements() + @GetMapping(value = "temp", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity tempAccessToken() { + String tempAccessToken = tokenService.createAccessToken(1L, "ROLE_USER"); + return ResponseEntity + .ok() + .body(new TokenResponse(tempAccessToken)); + + } + + @Operation(summary = "액세스 토큰을 재발급받는다.", + responses = { + @ApiResponse(responseCode = "200", description = "정상처리"), + @ApiResponse(responseCode = "401", description = "유효하지 않은 리프레쉬 토큰입니다.", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))) + }) + @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity refreshAccessToken( @CookieValue("refreshToken") String refreshToken ) { String accessToken = tokenService.getAccessTokensByRefreshToken(refreshToken); - return ResponseEntity.ok() + return ResponseEntity + .ok() .body(new TokenResponse(accessToken)); } - @DeleteMapping + @Operation(summary = "리프레시 토큰과 액세스 토큰을 삭제한다.", + responses = { + @ApiResponse(responseCode = "200", description = "정상처리"), + @ApiResponse(responseCode = "401", description = "쿠키를 찾을 수 없습니다.", + content = @Content(schema = @Schema(implementation = ErrorResponse.class))) + }) + @DeleteMapping(produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity expireRefreshToken( @CookieValue("refreshToken") String refreshToken ) { @@ -41,7 +75,8 @@ public ResponseEntity expireRefreshToken( ResponseCookie emptyCookie = CookieUtil.getEmptyCookie("refreshToken"); - return ResponseEntity.noContent() + return ResponseEntity + .noContent() .header(SET_COOKIE, emptyCookie.toString()).build(); } } diff --git a/src/main/java/com/dnd/gooding/global/token/api/response/TokenResponse.java b/src/main/java/com/dnd/gooding/global/token/api/response/TokenResponse.java index 775cdaf..5b8b8d1 100644 --- a/src/main/java/com/dnd/gooding/global/token/api/response/TokenResponse.java +++ b/src/main/java/com/dnd/gooding/global/token/api/response/TokenResponse.java @@ -1,6 +1,10 @@ package com.dnd.gooding.global.token.api.response; +import io.swagger.v3.oas.annotations.media.Schema; + +@Schema(description = "토큰") public record TokenResponse( + @Schema(description = "액세스 토큰") String accessToken ) { } diff --git a/src/main/resources/application-security.yml b/src/main/resources/application-security.yml index ad357df..d3b7eb5 100644 --- a/src/main/resources/application-security.yml +++ b/src/main/resources/application-security.yml @@ -14,6 +14,7 @@ spring: google: client-id: ${GOOGLE_CLIENT_ID} client-secret: ${GOOGLE_CLIENT_SECRET} + redirect-uri: ${GOOGLE_REDIRECT_URI} scope: profile,email mvc: static-path-pattern: /static/**