Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public class AuthController {
private final KakaoClient kakaoClient;
private final CookieProperties cookieProperties;

/**
* Issues a guest user access token and sets it as an HTTP-only cookie in the response.
*
* @return a response containing the guest user's token and the access token cookie.
*/
@GetMapping("/user/guest/token")
public ResponseEntity<TokenResponse> getGuestToken() {
TokenResponse tokenResponse = authService.createGuestUser();
Expand All @@ -44,11 +49,24 @@ public ResponseEntity<TokenResponse> getGuestToken() {
.body(tokenResponse);
}

/**
* Reissues an access token using the provided refresh token.
*
* @param refreshToken the refresh token from the Authorization header; must not be blank
* @return a response containing the new access token and related information
*/
@PutMapping("/user/reissue/token")
public RefreshResponse reissueAccessToken(@RequestHeader(value = "Authorization") @NotBlank String refreshToken) {
return refreshTokenService.execute(refreshToken);
}

/**
* Handles the Kakao OAuth2 login callback by exchanging the authorization code for a Kakao access token,
* obtaining or creating a user token, and setting it as an HTTP-only cookie in the response.
*
* @param code the OAuth2 authorization code received from Kakao after user authentication
* @return a response with status 200 OK and the access token set in an HTTP-only cookie
*/
@GetMapping("/login/oauth2/callback")
public ResponseEntity<Void> kakaoLoginCallback(@RequestParam String code) {
KakaoTokenResponse kakaoTokenResponse = kakaoClient.join(code);
Expand All @@ -62,6 +80,13 @@ public ResponseEntity<Void> kakaoLoginCallback(@RequestParam String code) {
.build();
}

/**
* Logs out the user by expiring the "accessToken" cookie.
*
* Sets an HTTP-only "accessToken" cookie with a max age of zero to remove it from the client, effectively logging out the user.
*
* @return a 200 OK response with the expired cookie set in the response header
*/
@GetMapping("/logout")
public ResponseEntity<Void> kakaoLogout() {
String cookie = expireCookie("accessToken").toString();
Expand All @@ -71,6 +96,13 @@ public ResponseEntity<Void> kakaoLogout() {
.build();
}

/**
* Creates an HTTP cookie with the specified name and value, applying properties from the configured CookieProperties.
*
* @param name the name of the cookie
* @param key the value to set for the cookie
* @return a ResponseCookie configured with security and path attributes
*/
private ResponseCookie createCookie(String name, String key) {
return ResponseCookie.from(name, key)
.httpOnly(cookieProperties.httpOnly())
Expand All @@ -83,6 +115,15 @@ private ResponseCookie createCookie(String name, String key) {

}

/**
* Creates a ResponseCookie with the specified name that is immediately expired.
*
* The cookie is configured with properties from {@code cookieProperties} and a max age of zero,
* causing it to be removed from the client.
*
* @param name the name of the cookie to expire
* @return a ResponseCookie configured to expire immediately
*/
private ResponseCookie expireCookie(String name) {
return ResponseCookie.from(name, null)
.httpOnly(cookieProperties.httpOnly())
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/com/dnd/moddo/domain/auth/service/AuthService.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ public class AuthService {
@Value("${kakao.auth.redirect_uri}")
String redirect_uri;

/**
* Creates a new guest user with a unique email and returns a JWT token for authentication.
*
* The guest user is assigned the name "Guest" and is not marked as a member.
*
* @return a JWT token representing the newly created guest user
*/
@Transactional
public TokenResponse createGuestUser() {
String guestEmail = "guest-" + UUID.randomUUID() + "@guest.com";
Expand All @@ -42,6 +49,17 @@ public TokenResponse createGuestUser() {
guestUser.getIsMember());
}

/**
* Creates and persists a new user with the specified email, name, and membership status.
*
* The user is assigned the USER authority, a null profile, the current time as the creation date,
* and an expiration date set to one month from creation.
*
* @param email the user's email address
* @param name the user's display name
* @param isMember whether the user is a registered member
* @return the saved User entity
*/
private User createUser(String email, String name, boolean isMember) {
User user = User.builder()
.email(email)
Expand All @@ -56,6 +74,14 @@ private User createUser(String email, String name, boolean isMember) {
return userRepository.save(user);
}

/**
* Retrieves or creates a user based on Kakao OAuth profile and returns a JWT token for authentication.
*
* If a user with the Kakao email does not exist, a new user is created using the Kakao profile information and marked as a member.
*
* @param token the Kakao OAuth access token
* @return a JWT token response containing authentication details for the Kakao user
*/
@Transactional
public TokenResponse getOrCreateKakaoUserToken(String token) {
KakaoProfile kakaoProfile = kakaoClient.getKakaoProfile(token);
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/com/dnd/moddo/domain/auth/service/KakaoClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ public class KakaoClient {

private final RestClient.Builder builder;

/**
* Exchanges an authorization code for a Kakao OAuth access token.
*
* @param code the authorization code received from Kakao after user authentication
* @return the response containing the Kakao OAuth access token and related information
* @throws ModdoException if an HTTP error occurs during the token request
* @throws IllegalArgumentException if a non-HTTP error occurs during the token request
*/
public KakaoTokenResponse join(String code) {
RestClient restClient = builder.build();

Expand Down Expand Up @@ -59,6 +67,13 @@ public KakaoTokenResponse join(String code) {
}
}

/**
* Retrieves the Kakao user profile associated with the provided access token.
*
* @param token the OAuth access token issued by Kakao
* @return the user's Kakao profile information
* @throws ModdoException if an HTTP error occurs or the profile cannot be retrieved
*/
public KakaoProfile getKakaoProfile(String token) {
RestClient restClient = builder.build();

Expand Down
19 changes: 19 additions & 0 deletions src/test/java/com/dnd/moddo/global/support/UserTestFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@
import com.dnd.moddo.domain.user.entity.User;

public class UserTestFactory {
/**
* Creates a default guest User instance with preset values for testing.
*
* The returned User has the name "연노른자", email "guest-UUID1@guest.com", profile image "profile.png",
* a boolean flag set to false, authority set to USER, and timestamps for creation and expiration
* set to the current time and seven days later, respectively.
*
* @return a User object representing a default guest user for test scenarios
*/
public static User createGuestDefault() {
LocalDateTime time = LocalDateTime.now();

Expand All @@ -20,6 +29,16 @@ public static User createGuestDefault() {
time.plusDays(7));
}

/**
* Creates a test User instance with the specified email and default attributes.
*
* The returned User has the name "연노른자", the provided email, profile image "profile.png",
* a boolean flag set to true, authority set to USER, and timestamps for creation and expiration
* set to the current time and seven days later, respectively.
*
* @param email the email address to assign to the User
* @return a User instance configured for testing with the given email
*/
public static User createWithEmail(String email) {
LocalDateTime time = LocalDateTime.now();

Expand Down
Loading