[api] SsoController.java, AuthController.java 컨벤션 맞춰 변경

This commit is contained in:
2026-05-22 11:55:48 +09:00
parent 3a4f4679c0
commit 7b10ef0db8
23 changed files with 508 additions and 293 deletions
@@ -4,14 +4,12 @@ import com.alist.api.common.response.ApiResponse;
import com.alist.api.common.response.ApiResponseCode; import com.alist.api.common.response.ApiResponseCode;
import com.alist.api.common.utils.SessionUtil; import com.alist.api.common.utils.SessionUtil;
import com.alist.api.config.jwt.JwtTokenProvider; import com.alist.api.config.jwt.JwtTokenProvider;
import com.alist.api.modules.auth.dto.SsoExchangeDto;
import com.alist.api.modules.auth.dto.LoginDto; import com.alist.api.modules.auth.dto.LoginDto;
import com.alist.api.modules.auth.dto.TokenDto; import com.alist.api.modules.auth.form.AuthApiKeyLoginForm;
import com.alist.api.modules.auth.form.ApikeyLoginForm; import com.alist.api.modules.auth.form.AuthTokenForm;
import com.alist.api.modules.auth.form.TokenForm;
import com.alist.api.modules.auth.service.SsoService;
import com.alist.api.modules.auth.service.AuthService; import com.alist.api.modules.auth.service.AuthService;
import com.alist.api.modules.auth.vo.TokenVo; import com.alist.api.modules.auth.service.SsoService;
import com.alist.api.modules.auth.vo.*;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
@@ -21,9 +19,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@Tag(name = "102. 엑세스 토큰 발급", description = "엑세스 토큰 발급") @Tag(name = "102. 엑세스 토큰 발급", description = "엑세스 토큰 발급")
@RestController @RestController
@RequestMapping("/auth") @RequestMapping("/auth")
@@ -55,93 +50,96 @@ public class AuthController {
public AuthController(SsoService ssoService, JwtTokenProvider jwtTokenProvider, AuthService authService) { public AuthController(SsoService ssoService, JwtTokenProvider jwtTokenProvider, AuthService authService) {
this.ssoService = ssoService; this.ssoService = ssoService;
this.jwtTokenProvider = jwtTokenProvider; this.jwtTokenProvider = jwtTokenProvider;
this.authService = authService; this.authService = authService;
}
@Operation(
summary = "엑세스 토큰 발급 (테스트용 실사용X)",
description = "엑세스 토큰이 발급됩니다. (테스트용 실사용X)"
)
@PostMapping("/token")
public ResponseEntity<ApiResponse<TokenVo>> token(@Valid @RequestBody TokenForm tokenForm) {
TokenVo tokenVo = new TokenVo();
tokenVo.setAccessToken(jwtTokenProvider.createToken(tokenForm.toTokenDto().getId()));
return ApiResponse.entity(tokenVo, ApiResponseCode.CODE_2001, "엑세스 토큰");
} }
@Operation( @Operation(
summary = "SSO 기반 토큰 발급", summary = "엑세스 토큰 발급 (테스트용 실사용X)"
description = "ALIST_SSO 쿠키 기준으로 SSO 로그인 상태를 확인한 뒤 accessToken, refreshToken 쿠키를 발급니다." , description = "엑세스 토큰이 발급니다. (테스트용 실사용X)"
)
@PostMapping("/token")
public ResponseEntity<ApiResponse<AuthTokenVo>> authToken(@Valid @RequestBody AuthTokenForm authTokenForm) {
AuthTokenVo authTokenVo = new AuthTokenVo();
authTokenVo.setAccessToken(jwtTokenProvider.createToken(authTokenForm.toDto().getId()));
return ApiResponse.entity(authTokenVo, ApiResponseCode.CODE_2001, "엑세스 토큰");
}
@Operation(
summary = "SSO 기반 토큰 발급"
, description = "ALIST_SSO 쿠키 기준으로 SSO 로그인 상태를 확인한 뒤 accessToken, refreshToken 쿠키를 발급합니다."
) )
@PostMapping("/access") @PostMapping("/access")
public ResponseEntity<ApiResponse<Map<String, Object>>> access( public ResponseEntity<ApiResponse<AuthAccessVo>> authAccess(
HttpServletRequest request, HttpServletRequest request,
HttpServletResponse response HttpServletResponse response
) { ) {
String ssoSessionId = SessionUtil.resolveSsoCookieValue(request, ssoCookieName); String ssoSessionId = SessionUtil.resolveSsoCookieValue(request, ssoCookieName);
SsoExchangeDto ssoSession = ssoService.loginChecked(ssoSessionId); SsoExchangeVo ssoExchangeVo = ssoService.selectSsoLoginChecked(ssoSessionId);
if (ssoSession == null) { AuthAccessVo authAccessVo = new AuthAccessVo();
return ApiResponse.entity(Map.of("isAccessToken", false), ApiResponseCode.CODE_401);
if (ssoExchangeVo == null) {
authAccessVo.setAccessToken(false);
return ApiResponse.entity(authAccessVo, ApiResponseCode.CODE_401);
} }
String accessToken = jwtTokenProvider.createAccessToken(ssoSession.getUserTokenIdx(), ssoSession.getUserRole()); String accessToken = jwtTokenProvider.createAccessToken(ssoExchangeVo.getUserTokenIdx(), ssoExchangeVo.getUserRole());
String refreshToken = jwtTokenProvider.createRefreshToken(ssoSession.getUserTokenIdx()); String refreshToken = jwtTokenProvider.createRefreshToken(ssoExchangeVo.getUserTokenIdx());
LoginDto loginDto = new LoginDto(); LoginDto loginDto = new LoginDto();
loginDto.setUserTokenIdx(ssoSession.getUserTokenIdx()); loginDto.setUserTokenIdx(ssoExchangeVo.getUserTokenIdx());
loginDto.setRefreshToken(refreshToken); loginDto.setRefreshToken(refreshToken);
authService.updateRefreshToken(loginDto); authService.updateRefreshToken(loginDto);
SessionUtil.addTokenCookie(response, "accessToken", accessToken, cookieDomain, cookieSecure, cookieSameSite, accessTokenValiditySeconds); SessionUtil.addTokenCookie(response, "accessToken", accessToken, cookieDomain, cookieSecure, cookieSameSite, accessTokenValiditySeconds);
SessionUtil.addTokenCookie(response,"refreshToken", refreshToken, cookieDomain, cookieSecure, cookieSameSite, refreshTokenValiditySeconds); SessionUtil.addTokenCookie(response, "refreshToken", refreshToken, cookieDomain, cookieSecure, cookieSameSite, refreshTokenValiditySeconds);
Map<String, Object> result = new HashMap<>(); authAccessVo.setAccessToken(true);
result.put("isAccessToken", true); authAccessVo.setUserIdx(ssoExchangeVo.getUserIdx());
result.put("userIdx", ssoSession.getUserIdx()); authAccessVo.setUserId(ssoExchangeVo.getUserId());
result.put("userId", ssoSession.getUserId()); authAccessVo.setUserRole(ssoExchangeVo.getUserRole());
result.put("userRole", ssoSession.getUserRole()); authAccessVo.setUserType(ssoExchangeVo.getUserType());
result.put("userType", ssoSession.getUserType());
return ApiResponse.entity(result, ApiResponseCode.CODE_2001, "토큰"); return ApiResponse.entity(authAccessVo, ApiResponseCode.CODE_2001, "토큰");
} }
@Operation( @Operation(
summary = "리프레시 토큰으로 엑세스 토큰 재발급", summary = "리프레시 토큰으로 엑세스 토큰 재발급"
description = "리프레시 토큰으로 엑세스 토큰 재발급" , description = "리프레시 토큰으로 엑세스 토큰 재발급"
) )
@PostMapping("/refresh") @PostMapping("/refresh")
public ResponseEntity<ApiResponse<Map<String, Object>>> refresh( public ResponseEntity<ApiResponse<AuthRefreshVo>> authRefresh(
@CookieValue(name = "refreshToken", required = false) String refreshToken @CookieValue(name = "refreshToken", required = false) String refreshToken
, HttpServletResponse response , HttpServletResponse response
) { ) {
AuthRefreshVo authRefreshVo = authService.selectAuthRefresh(refreshToken);
LoginDto result = authService.refreshByToken(refreshToken); if (authRefreshVo == null) {
AuthRefreshVo authRefreshVo1 = new AuthRefreshVo();
if (result == null) { authRefreshVo1.setRefreshed(false);
return ApiResponse.entity(Map.of("refreshed", false), ApiResponseCode.CODE_401); return ApiResponse.entity(authRefreshVo1, ApiResponseCode.CODE_401);
} }
SessionUtil.addTokenCookie(response, "accessToken", result.getAccessToken(), cookieDomain, cookieSecure, cookieSameSite, accessTokenValiditySeconds); SessionUtil.addTokenCookie(response, "accessToken", authRefreshVo.getAccessToken(), cookieDomain, cookieSecure, cookieSameSite, accessTokenValiditySeconds);
SessionUtil.addTokenCookie(response, "refreshToken", result.getRefreshToken(), cookieDomain, cookieSecure, cookieSameSite, refreshTokenValiditySeconds); SessionUtil.addTokenCookie(response, "refreshToken", authRefreshVo.getRefreshToken(), cookieDomain, cookieSecure, cookieSameSite, refreshTokenValiditySeconds);
return ApiResponse.entity(Map.of("refreshed", true), ApiResponseCode.CODE_200); return ApiResponse.entity(authRefreshVo, ApiResponseCode.CODE_200);
} }
@Operation( @Operation(
summary = "API Key 로그인", summary = "API Key 로그인"
description = "API Key로 인증하고 JSON으로 토큰을 반환합니다. (OpenAPI/외부 서비스용)" , description = "API Key로 인증하고 JSON으로 토큰을 반환합니다. (OpenAPI/외부 서비스용)"
) )
@PostMapping("/apiKeyLogin") @PostMapping("/apiKeyLogin")
public ResponseEntity<ApiResponse<LoginDto>> apiKeyLogin(@Valid @RequestBody ApikeyLoginForm apiKeyLoginForm) { public ResponseEntity<ApiResponse<AuthApiKeyLoginVo>> authApiKeyLogin(@Valid @RequestBody AuthApiKeyLoginForm authApiKeyLoginForm) {
LoginDto result = authService.selectUserApiKeyLogin(apiKeyLoginForm.toLoginDto()); AuthApiKeyLoginVo authApiKeyLoginVo = authService.selectAuthApiKeyLogin(authApiKeyLoginForm.toDto());
if (result.getResultCode() == 2003) { if (authApiKeyLoginVo.getResultCode() == 2003) {
return ApiResponse.entity(result, ApiResponseCode.CODE_2003); return ApiResponse.entity(authApiKeyLoginVo, ApiResponseCode.CODE_2003);
} }
return ApiResponse.entity(result, ApiResponseCode.CODE_2001, "엑세스 토큰"); return ApiResponse.entity(authApiKeyLoginVo, ApiResponseCode.CODE_2001, "엑세스 토큰");
} }
} }
@@ -3,13 +3,14 @@ package com.alist.api.modules.auth;
import com.alist.api.common.response.ApiResponse; import com.alist.api.common.response.ApiResponse;
import com.alist.api.common.response.ApiResponseCode; import com.alist.api.common.response.ApiResponseCode;
import com.alist.api.common.utils.SessionUtil; import com.alist.api.common.utils.SessionUtil;
import com.alist.api.modules.auth.dto.SsoExchangeDto;
import com.alist.api.modules.auth.dto.SsoLoginCheckDto;
import com.alist.api.modules.auth.dto.SsoLoginDto;
import com.alist.api.modules.auth.form.SsoExchangeForm; import com.alist.api.modules.auth.form.SsoExchangeForm;
import com.alist.api.modules.auth.form.SsoLoginForm; import com.alist.api.modules.auth.form.SsoLoginForm;
import com.alist.api.modules.auth.service.SsoService;
import com.alist.api.modules.auth.service.AuthService; import com.alist.api.modules.auth.service.AuthService;
import com.alist.api.modules.auth.service.SsoService;
import com.alist.api.modules.auth.vo.SsoExchangeVo;
import com.alist.api.modules.auth.vo.SsoLoginCheckedVo;
import com.alist.api.modules.auth.vo.SsoLoginVo;
import com.alist.api.modules.auth.vo.SsoLogoutVo;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
@@ -20,8 +21,6 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.net.URI; import java.net.URI;
import java.util.HashMap;
import java.util.Map;
@Tag(name = "101. SSO 인증", description = "공통 로그인, 인가 코드 발급, 코드 교환, 로그아웃 관련 API") @Tag(name = "101. SSO 인증", description = "공통 로그인, 인가 코드 발급, 코드 교환, 로그아웃 관련 API")
@RestController @RestController
@@ -50,126 +49,124 @@ public class SsoController {
} }
@Operation( @Operation(
summary = "SSO 로그인", summary = "SSO 로그인"
description = "아이디/비밀번호로 공통 SSO 로그인 상태를 생성하고 HttpOnly 쿠키를 발급합니다." , description = "아이디/비밀번호로 공통 SSO 로그인 상태를 생성하고 HttpOnly 쿠키를 발급합니다."
) )
@PostMapping("/login") @PostMapping("/login")
public ResponseEntity<ApiResponse<SsoLoginCheckDto>> login( public ResponseEntity<ApiResponse<SsoLoginVo>> ssoLogin(
@Valid @RequestBody SsoLoginForm ssoLoginForm @Valid @RequestBody SsoLoginForm ssoLoginForm
, HttpServletRequest request
, HttpServletResponse response , HttpServletResponse response
) { ) {
SsoLoginDto ssoLoginDto = ssoService.login(ssoLoginForm.toSsoLoginDto(), request); SsoLoginVo ssoLoginVo = ssoService.selectSsoLogin(ssoLoginForm.toDto());
SsoLoginCheckDto result = new SsoLoginCheckDto(); if (ssoLoginVo.getResultCode() == 2003) {
SsoLoginVo ssoLoginVo1 = new SsoLoginVo();
if (ssoLoginDto.getResultCode() == 2003) { ssoLoginVo1.setLoginIn(false);
result.setLoginIn(false); return ApiResponse.entity(ssoLoginVo1, ApiResponseCode.CODE_2003);
return ApiResponse.entity(result, ApiResponseCode.CODE_2003);
} }
SessionUtil.addTokenCookie(response, ssoCookieName, ssoLoginDto.getSsoSessionId(), cookieDomain, cookieSecure, cookieSameSite, ssoSessionTtlSeconds); SessionUtil.addTokenCookie(response, ssoCookieName, ssoLoginVo.getSsoSessionId(), cookieDomain, cookieSecure, cookieSameSite, ssoSessionTtlSeconds);
result.setLoginIn(true); ssoLoginVo.setLoginIn(true);
result.setId(ssoLoginDto.getUserId()); ssoLoginVo.setId(ssoLoginVo.getUserId());
result.setUserIdx(ssoLoginDto.getUserIdx());
result.setUserRole(ssoLoginDto.getUserRole());
result.setUserType(ssoLoginDto.getUserType());
return ApiResponse.entity(result, ApiResponseCode.CODE_2001, "SSO 로그인"); return ApiResponse.entity(ssoLoginVo, ApiResponseCode.CODE_2001, "SSO 로그인");
} }
@Operation( @Operation(
summary = "SSO 로그인 상태 확인", summary = "SSO 로그인 상태 확인"
description = "SSO 쿠키 기준으로 현재 공통 로그인 상태가 유효한지 확인하고, access/refresh 토큰 존재 여부도 함께 반환합니다." , description = "SSO 쿠키 기준으로 현재 공통 로그인 상태가 유효한지 확인하고, access/refresh 토큰 존재 여부도 함께 반환합니다."
) )
@GetMapping("/loginChecked") @GetMapping("/loginChecked")
public ResponseEntity<ApiResponse<Map<String, Object>>> loginChecked( public ResponseEntity<ApiResponse<SsoLoginCheckedVo>> ssoLoginChecked(
HttpServletRequest request HttpServletRequest request
, HttpServletResponse response , HttpServletResponse response
) { ) {
String ssoSessionId = SessionUtil.resolveSsoCookieValue(request, ssoCookieName); String ssoSessionId = SessionUtil.resolveSsoCookieValue(request, ssoCookieName);
Map<String, Object> result = new HashMap<>(); SsoLoginCheckedVo ssoLoginCheckedVo = new SsoLoginCheckedVo();
SsoExchangeDto ssoSession = ssoService.loginChecked(ssoSessionId); SsoExchangeVo ssoExchangeVo = ssoService.selectSsoLoginChecked(ssoSessionId);
String accessToken = SessionUtil.resolveSsoCookieValue(request, "accessToken"); String accessToken = SessionUtil.resolveSsoCookieValue(request, "accessToken");
String refreshToken = SessionUtil.resolveSsoCookieValue(request, "refreshToken"); String refreshToken = SessionUtil.resolveSsoCookieValue(request, "refreshToken");
result.put("isAccessToken", accessToken != null && !accessToken.trim().isEmpty()); ssoLoginCheckedVo.setAccessToken(accessToken != null && !accessToken.trim().isEmpty());
result.put("isRefreshToken", refreshToken != null && !refreshToken.trim().isEmpty()); ssoLoginCheckedVo.setRefreshToken(refreshToken != null && !refreshToken.trim().isEmpty());
if (ssoSession == null) { if (ssoExchangeVo == null) {
result.put("loggedIn", false); ssoLoginCheckedVo.setLoggedIn(false);
return ApiResponse.entity(result, ApiResponseCode.CODE_200); return ApiResponse.entity(ssoLoginCheckedVo, ApiResponseCode.CODE_200);
} }
SessionUtil.addTokenCookie(response, ssoCookieName, ssoSession.getSsoSessionId(), cookieDomain, cookieSecure, cookieSameSite,ssoSessionTtlSeconds); SessionUtil.addTokenCookie(response, ssoCookieName, ssoExchangeVo.getSsoSessionId(), cookieDomain, cookieSecure, cookieSameSite, ssoSessionTtlSeconds);
result.put("loggedIn", true); ssoLoginCheckedVo.setLoggedIn(true);
result.put("ssoSessionId", ssoSession.getSsoSessionId()); ssoLoginCheckedVo.setSsoSessionId(ssoExchangeVo.getSsoSessionId());
result.put("userId", ssoSession.getUserId()); ssoLoginCheckedVo.setUserId(ssoExchangeVo.getUserId());
result.put("userIdx", ssoSession.getUserIdx()); ssoLoginCheckedVo.setUserIdx(ssoExchangeVo.getUserIdx());
result.put("userTokenIdx", ssoSession.getUserTokenIdx()); ssoLoginCheckedVo.setUserTokenIdx(ssoExchangeVo.getUserTokenIdx());
result.put("userRole", ssoSession.getUserRole()); ssoLoginCheckedVo.setUserRole(ssoExchangeVo.getUserRole());
result.put("userType", ssoSession.getUserType()); ssoLoginCheckedVo.setUserType(ssoExchangeVo.getUserType());
return ApiResponse.entity(result, ApiResponseCode.CODE_200); return ApiResponse.entity(ssoLoginCheckedVo, ApiResponseCode.CODE_200);
} }
@Operation( @Operation(
summary = "SSO 인가 코드 발급", summary = "SSO 인가 코드 발급"
description = "공통 로그인 상태를 확인한 뒤 대상 서비스로 이동할 1회용 인가 코드를 발급하고 redirectUri 로 리다이렉트합니다." , description = "공통 로그인 상태를 확인한 뒤 대상 서비스로 이동할 1회용 인가 코드를 발급하고 redirectUri 로 리다이렉트합니다."
) )
@GetMapping("/authorize") @GetMapping("/authorize")
public ResponseEntity<Void> authorize( public ResponseEntity<Void> ssoAuthorize(
@RequestParam("clientId") String clientId @RequestParam("clientId") String clientId
, @RequestParam("redirectUri") String redirectUri , @RequestParam("redirectUri") String redirectUri
, @RequestParam(value = "state", required = false) String state , @RequestParam(value = "state", required = false) String state
, HttpServletRequest request , HttpServletRequest request
) { ) {
String ssoSessionId = SessionUtil.resolveSsoCookieValue(request, ssoCookieName); String ssoSessionId = SessionUtil.resolveSsoCookieValue(request, ssoCookieName);
String redirectUrl = ssoService.authorize(clientId, redirectUri, state, ssoSessionId); String redirectUrl = ssoService.selectSsoAuthorize(clientId, redirectUri, state, ssoSessionId);
return ResponseEntity.status(302).location(URI.create(redirectUrl)).build(); return ResponseEntity.status(302).location(URI.create(redirectUrl)).build();
} }
@Operation( @Operation(
summary = "SSO 인가 코드 교환", summary = "SSO 인가 코드 교환"
description = "서비스가 전달받은 1회용 인가 코드를 검증하고, 자체 세션 생성에 필요한 사용자 정보를 반환합니다." , description = "서비스가 전달받은 1회용 인가 코드를 검증하고, 자체 세션 생성에 필요한 사용자 정보를 반환합니다."
) )
@PostMapping("/exchange") @PostMapping("/exchange")
public ResponseEntity<ApiResponse<SsoExchangeDto>> exchange( public ResponseEntity<ApiResponse<SsoExchangeVo>> ssoExchange(
@Valid @RequestBody SsoExchangeForm ssoExchangeForm @Valid @RequestBody SsoExchangeForm ssoExchangeForm
, HttpServletResponse response , HttpServletResponse response
) { ) {
SsoExchangeDto result = ssoService.exchange(ssoExchangeForm.toSsoExchangeDto()); SsoExchangeVo ssoExchangeVo = ssoService.selectSsoExchange(ssoExchangeForm.toDto());
SessionUtil.addTokenCookie(response, ssoCookieName, result.getSsoSessionId(), cookieDomain, cookieSecure, cookieSameSite, ssoSessionTtlSeconds); SessionUtil.addTokenCookie(response, ssoCookieName, ssoExchangeVo.getSsoSessionId(), cookieDomain, cookieSecure, cookieSameSite, ssoSessionTtlSeconds);
return ApiResponse.entity(result, ApiResponseCode.CODE_2001, "SSO code 교환"); return ApiResponse.entity(ssoExchangeVo, ApiResponseCode.CODE_2001, "SSO code 교환");
} }
@Operation( @Operation(
summary = "SSO 로그아웃", summary = "SSO 로그아웃"
description = "공통 로그인 세션을 만료시켜 이후 authorize 및 서비스 접근 시 재로그인이 필요하도록 처리합니다." , description = "공통 로그인 세션을 만료시켜 이후 authorize 및 서비스 접근 시 재로그인이 필요하도록 처리합니다."
) )
@PostMapping("/logout") @PostMapping("/logout")
public ResponseEntity<ApiResponse<Map<String, Object>>> logout( public ResponseEntity<ApiResponse<SsoLogoutVo>> ssoLogout(
HttpServletRequest request HttpServletRequest request
, HttpServletResponse response , HttpServletResponse response
, @CookieValue(name = "refreshToken", required = false) String refreshToken , @CookieValue(name = "refreshToken", required = false) String refreshToken
) { ) {
String ssoSessionId = SessionUtil.resolveSsoCookieValue(request, ssoCookieName); String ssoSessionId = SessionUtil.resolveSsoCookieValue(request, ssoCookieName);
ssoService.logout(ssoSessionId); ssoService.updateSsoLogout(ssoSessionId);
authService.clearRefreshToken(refreshToken); authService.clearRefreshToken(refreshToken);
SessionUtil.expireCookie(response, ssoCookieName, cookieDomain, cookieSecure, cookieSameSite); SessionUtil.expireCookie(response, ssoCookieName, cookieDomain, cookieSecure, cookieSameSite);
SessionUtil.expireCookie(response, "accessToken", cookieDomain, cookieSecure, cookieSameSite); SessionUtil.expireCookie(response, "accessToken", cookieDomain, cookieSecure, cookieSameSite);
SessionUtil.expireCookie(response, "refreshToken", cookieDomain, cookieSecure, cookieSameSite); SessionUtil.expireCookie(response, "refreshToken", cookieDomain, cookieSecure, cookieSameSite);
return ApiResponse.entity(Map.of("logout", true), ApiResponseCode.CODE_200); SsoLogoutVo ssoLogoutVo = new SsoLogoutVo();
ssoLogoutVo.setLogout(true);
return ApiResponse.entity(ssoLogoutVo, ApiResponseCode.CODE_200);
} }
} }
@@ -0,0 +1,24 @@
package com.alist.api.modules.auth.dto;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Schema(description = "테스트용 토큰 발급 요청 DTO")
@Getter
@Setter
public class AuthTokenDto {
@Schema(description = "아이디")
private String id;
@Schema(description = "엑세스 토큰")
private String accessToken;
@Schema(description = "리플레시 토큰")
private String refreshToken;
@JsonIgnore
@Schema(hidden = true)
private int resultCode;
}
@@ -17,7 +17,7 @@ public class SsoLoginDto {
private String userRole; private String userRole;
private String userType; private String userType;
public LoginDto toLoginDto() { public LoginDto toDto() {
LoginDto loginDto = new LoginDto(); LoginDto loginDto = new LoginDto();
loginDto.setId(this.id); loginDto.setId(this.id);
loginDto.setPassword(this.password); loginDto.setPassword(this.password);
@@ -9,18 +9,18 @@ import lombok.Setter;
@Schema(description = "API Key 로그인 요청 폼") @Schema(description = "API Key 로그인 요청 폼")
@Getter @Getter
@Setter @Setter
public class ApikeyLoginForm { public class AuthApiKeyLoginForm {
@Schema( @Schema(
description = "사용자 API Key", description = "사용자 API Key"
example = "YjeWJr9-N-XaJ7ix2M2spnfjOyG9nTmRlY9t6sKw4_M", , example = "YjeWJr9-N-XaJ7ix2M2spnfjOyG9nTmRlY9t6sKw4_M"
requiredMode = Schema.RequiredMode.REQUIRED , requiredMode = Schema.RequiredMode.REQUIRED
) )
@NotBlank(message = "apiKey를 입력해주세요.") @NotBlank(message = "apiKey를 입력해주세요.")
private String userApiKey; private String userApiKey;
public LoginDto toLoginDto() { public LoginDto toDto() {
LoginDto loginDto = new LoginDto(); LoginDto loginDto = new LoginDto();
loginDto.setUserApiKey(this.userApiKey.trim()); loginDto.setUserApiKey(userApiKey == null ? null : userApiKey.trim());
return loginDto; return loginDto;
} }
@@ -0,0 +1,24 @@
package com.alist.api.modules.auth.form;
import com.alist.api.modules.auth.dto.AuthTokenDto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Schema(description = "토큰 요청 폼")
public class AuthTokenForm {
@NotBlank(message = "사용자명은 필수입니다.")
@Schema(description = "사용자명", example = "test")
private String id;
public AuthTokenDto toDto() {
AuthTokenDto authTokenDto = new AuthTokenDto();
authTokenDto.setId(this.id.trim());
return authTokenDto;
}
}
@@ -11,22 +11,22 @@ import lombok.Setter;
@Setter @Setter
public class SsoExchangeForm { public class SsoExchangeForm {
@Schema( @Schema(
description = "SSO 인가 코드", description = "SSO 인가 코드"
example = "authorization-code", , example = "authorization-code"
requiredMode = Schema.RequiredMode.REQUIRED , requiredMode = Schema.RequiredMode.REQUIRED
) )
@NotBlank(message = "인가 코드는 필수입니다.") @NotBlank(message = "인가 코드는 필수입니다.")
private String code; private String code;
@Schema( @Schema(
description = "SSO 클라이언트 ID", description = "SSO 클라이언트 ID"
example = "alist-main", , example = "alist-main"
requiredMode = Schema.RequiredMode.REQUIRED , requiredMode = Schema.RequiredMode.REQUIRED
) )
@NotBlank(message = "클라이언트 ID는 필수입니다.") @NotBlank(message = "클라이언트 ID는 필수입니다.")
private String clientId; private String clientId;
public SsoExchangeDto toSsoExchangeDto() { public SsoExchangeDto toDto() {
SsoExchangeDto ssoExchangeDto = new SsoExchangeDto(); SsoExchangeDto ssoExchangeDto = new SsoExchangeDto();
ssoExchangeDto.setCode(code == null ? null : code.trim()); ssoExchangeDto.setCode(code == null ? null : code.trim());
ssoExchangeDto.setClientId(clientId == null ? null : clientId.trim()); ssoExchangeDto.setClientId(clientId == null ? null : clientId.trim());
@@ -11,22 +11,22 @@ import lombok.Setter;
@Setter @Setter
public class SsoLoginForm { public class SsoLoginForm {
@Schema( @Schema(
description = "회원 아이디", description = "회원 아이디"
example = "test", , example = "test"
requiredMode = Schema.RequiredMode.REQUIRED , requiredMode = Schema.RequiredMode.REQUIRED
) )
@NotBlank(message = "아이디는 필수입니다.") @NotBlank(message = "아이디는 필수입니다.")
private String id; private String id;
@Schema( @Schema(
description = "비밀번호", description = "비밀번호"
example = "password1234", , example = "password1234"
requiredMode = Schema.RequiredMode.REQUIRED , requiredMode = Schema.RequiredMode.REQUIRED
) )
@NotBlank(message = "비밀번호는 필수입니다.") @NotBlank(message = "비밀번호는 필수입니다.")
private String password; private String password;
public SsoLoginDto toSsoLoginDto() { public SsoLoginDto toDto() {
SsoLoginDto ssoLoginDto = new SsoLoginDto(); SsoLoginDto ssoLoginDto = new SsoLoginDto();
ssoLoginDto.setId(id == null ? null : id.trim()); ssoLoginDto.setId(id == null ? null : id.trim());
ssoLoginDto.setPassword(password == null ? null : password.trim()); ssoLoginDto.setPassword(password == null ? null : password.trim());
@@ -1,24 +0,0 @@
package com.alist.api.modules.auth.form;
import com.alist.api.modules.auth.dto.TokenDto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Schema(description = "토큰 요청 폼")
public class TokenForm {
@NotBlank(message = "사용자명은 필수입니다.")
@Schema(description = "사용자명", example = "test")
private String id;
public TokenDto toTokenDto() {
TokenDto tokenDto = new TokenDto();
tokenDto.setId(this.id.trim());
return tokenDto;
}
}
@@ -4,7 +4,6 @@ import com.alist.api.modules.auth.dto.LoginDto;
import com.alist.api.modules.auth.vo.LoginTokenVo; import com.alist.api.modules.auth.vo.LoginTokenVo;
import com.alist.api.modules.auth.vo.LoginVo; import com.alist.api.modules.auth.vo.LoginVo;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper @Mapper
public interface AuthMapper { public interface AuthMapper {
@@ -20,5 +19,5 @@ public interface AuthMapper {
void clearRefreshTokenByUserTokenIdx(int userTokenIdx); void clearRefreshTokenByUserTokenIdx(int userTokenIdx);
void updateLoginByLastAt(LoginDto loginDto); void updateLoginByLastAt(LoginDto loginDto);
} }
@@ -4,6 +4,8 @@ import com.alist.api.config.jwt.JwtTokenProvider;
import com.alist.api.config.properties.JwtProperties; import com.alist.api.config.properties.JwtProperties;
import com.alist.api.modules.auth.dto.LoginDto; import com.alist.api.modules.auth.dto.LoginDto;
import com.alist.api.modules.auth.mapper.AuthMapper; import com.alist.api.modules.auth.mapper.AuthMapper;
import com.alist.api.modules.auth.vo.AuthApiKeyLoginVo;
import com.alist.api.modules.auth.vo.AuthRefreshVo;
import com.alist.api.modules.auth.vo.LoginTokenVo; import com.alist.api.modules.auth.vo.LoginTokenVo;
import com.alist.api.modules.auth.vo.LoginVo; import com.alist.api.modules.auth.vo.LoginVo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -28,70 +30,88 @@ public class AuthService {
this.jwtProperties = jwtProperties; this.jwtProperties = jwtProperties;
} }
// id login @Transactional
public LoginDto selectLogin(LoginDto loginDto) { public LoginVo selectLogin(LoginDto loginDto) {
LoginVo loginVo = authMapper.selectLogin(loginDto); LoginVo loginVo = authMapper.selectLogin(loginDto);
if (loginVo != null) { if (loginVo == null) {
if (passwordEncoder.matches(loginDto.getPassword(), loginVo.getPassword())) { LoginVo loginVo1 = new LoginVo();
loginVo1.setResultCode(2003);
loginDto.setUserIdx(loginVo.getUserIdx()); return loginVo1;
LoginTokenVo loginTokenVo = authMapper.selectUserTokenByUserId(loginDto);
if (loginTokenVo != null) {
loginDto.setAccessToken(jwtTokenProvider.createAccessToken(loginTokenVo.getUserTokenIdx(), loginTokenVo.getUserRole()));
loginDto.setRefreshToken(jwtTokenProvider.createRefreshToken(loginTokenVo.getUserTokenIdx()));
loginDto.setUserTokenIdx(loginTokenVo.getUserTokenIdx());
loginDto.setUserRole(loginTokenVo.getUserRole());
loginDto.setUserType(loginTokenVo.getUserType());
Instant now = Instant.now();
Instant expiresAt = now.plusSeconds(jwtProperties.getRefreshTokenValiditySeconds());
loginDto.setExpiresAt(expiresAt);
authMapper.updateRefreshToken(loginDto);
// 마지막 로그인 시간 추가
authMapper.updateLoginByLastAt(loginDto);
loginDto.setResultCode(2001);
} else {
loginDto.setResultCode(2003);
}
} else {
loginDto.setResultCode(2003);
}
} else {
loginDto.setResultCode(2003);
} }
return loginDto; if (!passwordEncoder.matches(loginDto.getPassword(), loginVo.getPassword())) {
} LoginVo loginVo1 = new LoginVo();
loginVo1.setResultCode(2003);
// api key login return loginVo1;
public LoginDto selectUserApiKeyLogin(LoginDto loginDto) {
if (loginDto.getUserApiKey() != null) {
LoginTokenVo loginTokenVo = authMapper.selectUserTokenByUserApiKey(loginDto);
if (loginTokenVo != null) {
loginDto.setAccessToken(jwtTokenProvider.createAccessToken(loginTokenVo.getUserTokenIdx(), loginTokenVo.getUserRole()));
loginDto.setRefreshToken(jwtTokenProvider.createRefreshToken(loginTokenVo.getUserTokenIdx()));
loginDto.setResultCode(2001);
} else {
loginDto.setResultCode(2003);
}
} else {
loginDto.setResultCode(2003);
} }
return loginDto; loginDto.setUserIdx(loginVo.getUserIdx());
LoginTokenVo loginTokenVo = authMapper.selectUserTokenByUserId(loginDto);
if (loginTokenVo == null) {
LoginVo loginVo1 = new LoginVo();
loginVo1.setResultCode(2003);
return loginVo1;
}
String accessToken = jwtTokenProvider.createAccessToken(loginTokenVo.getUserTokenIdx(), loginTokenVo.getUserRole());
String refreshToken = jwtTokenProvider.createRefreshToken(loginTokenVo.getUserTokenIdx());
Instant expiresAt = Instant.now().plusSeconds(jwtProperties.getRefreshTokenValiditySeconds());
loginVo.setAccessToken(accessToken);
loginVo.setRefreshToken(refreshToken);
loginVo.setUserTokenIdx(loginTokenVo.getUserTokenIdx());
loginVo.setUserRole(loginTokenVo.getUserRole());
loginVo.setUserType(loginTokenVo.getUserType());
loginVo.setExpiresAt(expiresAt);
loginVo.setResultCode(2001);
loginDto.setUserTokenIdx(loginVo.getUserTokenIdx());
loginDto.setRefreshToken(loginVo.getRefreshToken());
loginDto.setExpiresAt(loginVo.getExpiresAt());
authMapper.updateRefreshToken(loginDto);
authMapper.updateLoginByLastAt(loginDto);
return loginVo;
} }
public LoginDto refreshByToken(String refreshToken) { @Transactional
public AuthApiKeyLoginVo selectAuthApiKeyLogin(LoginDto loginDto) {
AuthApiKeyLoginVo authApiKeyLoginVo = new AuthApiKeyLoginVo();
if (loginDto.getUserApiKey() == null) {
authApiKeyLoginVo.setResultCode(2003);
return authApiKeyLoginVo;
}
LoginTokenVo loginTokenVo = authMapper.selectUserTokenByUserApiKey(loginDto);
if (loginTokenVo == null) {
authApiKeyLoginVo.setResultCode(2003);
return authApiKeyLoginVo;
}
String accessToken = jwtTokenProvider.createAccessToken(loginTokenVo.getUserTokenIdx(), loginTokenVo.getUserRole());
String refreshToken = jwtTokenProvider.createRefreshToken(loginTokenVo.getUserTokenIdx());
loginDto.setUserTokenIdx(loginTokenVo.getUserTokenIdx());
loginDto.setRefreshToken(refreshToken);
loginDto.setExpiresAt(Instant.now().plusSeconds(jwtProperties.getRefreshTokenValiditySeconds()));
authMapper.updateRefreshToken(loginDto);
authApiKeyLoginVo.setAccessToken(accessToken);
authApiKeyLoginVo.setRefreshToken(refreshToken);
authApiKeyLoginVo.setResultCode(2001);
return authApiKeyLoginVo;
}
@Transactional
public AuthRefreshVo selectAuthRefresh(String refreshToken) {
if (refreshToken == null || !jwtTokenProvider.validateToken(refreshToken)) { if (refreshToken == null || !jwtTokenProvider.validateToken(refreshToken)) {
return null; return null;
} }
@@ -112,14 +132,22 @@ public class AuthService {
return null; return null;
} }
LoginDto result = new LoginDto(); String newAccessToken = jwtTokenProvider.createAccessToken(tokenVo.getUserTokenIdx(), tokenVo.getUserRole());
result.setUserTokenIdx(userTokenIdx); String newRefreshToken = jwtTokenProvider.createRefreshToken(tokenVo.getUserTokenIdx());
result.setAccessToken(jwtTokenProvider.createAccessToken(tokenVo.getUserTokenIdx(), tokenVo.getUserRole()));
result.setRefreshToken(jwtTokenProvider.createRefreshToken(tokenVo.getUserTokenIdx()));
result.setExpiresAt(Instant.now().plusSeconds(jwtProperties.getRefreshTokenValiditySeconds()));
authMapper.updateRefreshToken(result); LoginDto loginDto = new LoginDto();
return result; loginDto.setUserTokenIdx(userTokenIdx);
loginDto.setRefreshToken(newRefreshToken);
loginDto.setExpiresAt(Instant.now().plusSeconds(jwtProperties.getRefreshTokenValiditySeconds()));
authMapper.updateRefreshToken(loginDto);
AuthRefreshVo authRefreshVo = new AuthRefreshVo();
authRefreshVo.setAccessToken(newAccessToken);
authRefreshVo.setRefreshToken(newRefreshToken);
authRefreshVo.setRefreshed(true);
return authRefreshVo;
} }
public void clearRefreshToken(String refreshToken) { public void clearRefreshToken(String refreshToken) {
@@ -2,10 +2,11 @@ package com.alist.api.modules.auth.service;
import com.alist.api.modules.auth.dto.SsoExchangeDto; import com.alist.api.modules.auth.dto.SsoExchangeDto;
import com.alist.api.modules.auth.dto.SsoLoginDto; import com.alist.api.modules.auth.dto.SsoLoginDto;
import com.alist.api.modules.auth.dto.LoginDto;
import com.alist.api.modules.auth.mapper.SsoMapper; import com.alist.api.modules.auth.mapper.SsoMapper;
import com.alist.api.modules.auth.vo.LoginVo;
import com.alist.api.modules.auth.vo.SsoClientVo; import com.alist.api.modules.auth.vo.SsoClientVo;
import jakarta.servlet.http.HttpServletRequest; import com.alist.api.modules.auth.vo.SsoExchangeVo;
import com.alist.api.modules.auth.vo.SsoLoginVo;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -32,18 +33,18 @@ public class SsoService {
this.ssoCodeTtl = Duration.ofSeconds(ssoCodeTtlSeconds); this.ssoCodeTtl = Duration.ofSeconds(ssoCodeTtlSeconds);
} }
public SsoLoginDto login(SsoLoginDto ssoLoginDto, HttpServletRequest request) { public SsoLoginVo selectSsoLogin(SsoLoginDto ssoLoginDto) {
LoginDto loginDto = authService.selectLogin(ssoLoginDto.toLoginDto()); LoginVo loginVo = authService.selectLogin(ssoLoginDto.toDto());
SsoLoginDto result = new SsoLoginDto(); SsoLoginVo ssoLoginVo = new SsoLoginVo();
result.setResultCode(loginDto.getResultCode()); ssoLoginVo.setResultCode(loginVo.getResultCode());
if (loginDto.getResultCode() == 2003) { if (loginVo.getResultCode() == 2003) {
return result; return ssoLoginVo;
} }
String ssoSessionId = "SSO_" + UUID.randomUUID(); String ssoSessionId = "SSO_" + UUID.randomUUID();
String latestSessionKey = "alist:sso:userIdx:" + loginDto.getUserIdx(); String latestSessionKey = "alist:sso:userIdx:" + loginVo.getUserIdx();
String sessionKey = "alist:sso:session:" + ssoSessionId; String sessionKey = "alist:sso:session:" + ssoSessionId;
String oldSsoSessionId = redisTemplate.opsForValue().get(latestSessionKey); String oldSsoSessionId = redisTemplate.opsForValue().get(latestSessionKey);
@@ -51,26 +52,26 @@ public class SsoService {
redisTemplate.delete("alist:sso:session:" + oldSsoSessionId); redisTemplate.delete("alist:sso:session:" + oldSsoSessionId);
} }
redisTemplate.opsForHash().put(sessionKey, "userIdx", String.valueOf(loginDto.getUserIdx())); redisTemplate.opsForHash().put(sessionKey, "userIdx", String.valueOf(loginVo.getUserIdx()));
redisTemplate.opsForHash().put(sessionKey, "userTokenIdx", String.valueOf(loginDto.getUserTokenIdx())); redisTemplate.opsForHash().put(sessionKey, "userTokenIdx", String.valueOf(loginVo.getUserTokenIdx()));
redisTemplate.opsForHash().put(sessionKey, "userId", loginDto.getId()); redisTemplate.opsForHash().put(sessionKey, "userId", loginVo.getId());
redisTemplate.opsForHash().put(sessionKey, "userRole", loginDto.getUserRole()); redisTemplate.opsForHash().put(sessionKey, "userRole", loginVo.getUserRole());
redisTemplate.opsForHash().put(sessionKey, "userType", loginDto.getUserType()); redisTemplate.opsForHash().put(sessionKey, "userType", loginVo.getUserType());
redisTemplate.expire(sessionKey, ssoSessionTtl); redisTemplate.expire(sessionKey, ssoSessionTtl);
redisTemplate.opsForValue().set(latestSessionKey, ssoSessionId, ssoSessionTtl); redisTemplate.opsForValue().set(latestSessionKey, ssoSessionId, ssoSessionTtl);
result.setSsoSessionId(ssoSessionId); ssoLoginVo.setSsoSessionId(ssoSessionId);
result.setUserId(loginDto.getId()); ssoLoginVo.setUserId(loginVo.getId());
result.setUserIdx(loginDto.getUserIdx()); ssoLoginVo.setUserIdx(loginVo.getUserIdx());
result.setUserRole(loginDto.getUserRole()); ssoLoginVo.setUserRole(loginVo.getUserRole());
result.setUserType(loginDto.getUserType()); ssoLoginVo.setUserType(loginVo.getUserType());
result.setResultCode(200); ssoLoginVo.setResultCode(200);
return result; return ssoLoginVo;
} }
public SsoExchangeDto loginChecked(String ssoSessionId) { public SsoExchangeVo selectSsoLoginChecked(String ssoSessionId) {
if (ssoSessionId == null || ssoSessionId.isBlank()) { if (ssoSessionId == null || ssoSessionId.isBlank()) {
return null; return null;
} }
@@ -94,18 +95,18 @@ public class SsoService {
String userRole = (String) redisTemplate.opsForHash().get(sessionKey, "userRole"); String userRole = (String) redisTemplate.opsForHash().get(sessionKey, "userRole");
String userType = (String) redisTemplate.opsForHash().get(sessionKey, "userType"); String userType = (String) redisTemplate.opsForHash().get(sessionKey, "userType");
SsoExchangeDto result = new SsoExchangeDto(); SsoExchangeVo ssoExchangeVo = new SsoExchangeVo();
result.setSsoSessionId(ssoSessionId); ssoExchangeVo.setSsoSessionId(ssoSessionId);
result.setUserId(userId); ssoExchangeVo.setUserId(userId);
result.setUserIdx(userIdx == null ? null : Integer.parseInt(userIdx)); ssoExchangeVo.setUserIdx(userIdx == null ? null : Integer.parseInt(userIdx));
result.setUserTokenIdx(userTokenIdx == null ? null : Integer.parseInt(userTokenIdx)); ssoExchangeVo.setUserTokenIdx(userTokenIdx == null ? null : Integer.parseInt(userTokenIdx));
result.setUserRole(userRole); ssoExchangeVo.setUserRole(userRole);
result.setUserType(userType); ssoExchangeVo.setUserType(userType);
return result; return ssoExchangeVo;
} }
public String authorize(String clientId, String redirectUri, String state, String ssoSessionId) { public String selectSsoAuthorize(String clientId, String redirectUri, String state, String ssoSessionId) {
if (ssoSessionId == null || ssoSessionId.isBlank()) { if (ssoSessionId == null || ssoSessionId.isBlank()) {
return "/login"; return "/login";
} }
@@ -158,7 +159,7 @@ public class SsoService {
return redirect.toString(); return redirect.toString();
} }
public SsoExchangeDto exchange(SsoExchangeDto ssoExchangeDto) { public SsoExchangeVo selectSsoExchange(SsoExchangeDto ssoExchangeDto) {
String codeKey = "alist:sso:code:" + ssoExchangeDto.getCode(); String codeKey = "alist:sso:code:" + ssoExchangeDto.getCode();
String ssoSessionId = (String) redisTemplate.opsForHash().get(codeKey, "ssoSessionId"); String ssoSessionId = (String) redisTemplate.opsForHash().get(codeKey, "ssoSessionId");
String clientId = (String) redisTemplate.opsForHash().get(codeKey, "clientId"); String clientId = (String) redisTemplate.opsForHash().get(codeKey, "clientId");
@@ -182,17 +183,18 @@ public class SsoService {
refreshSsoSessionTtl(ssoSessionId, userIdx); refreshSsoSessionTtl(ssoSessionId, userIdx);
redisTemplate.delete(codeKey); redisTemplate.delete(codeKey);
SsoExchangeDto result = new SsoExchangeDto(); SsoExchangeVo ssoExchangeVo = new SsoExchangeVo();
result.setUserId(userId); ssoExchangeVo.setUserId(userId);
result.setUserIdx(Integer.parseInt(userIdx)); ssoExchangeVo.setUserIdx(Integer.parseInt(userIdx));
result.setUserTokenIdx(Integer.parseInt(userTokenIdx)); ssoExchangeVo.setUserTokenIdx(Integer.parseInt(userTokenIdx));
result.setUserRole(userRole); ssoExchangeVo.setUserRole(userRole);
result.setUserType(userType); ssoExchangeVo.setUserType(userType);
result.setSsoSessionId(ssoSessionId); ssoExchangeVo.setSsoSessionId(ssoSessionId);
return result;
return ssoExchangeVo;
} }
public void logout(String ssoSessionId) { public void updateSsoLogout(String ssoSessionId) {
if (ssoSessionId == null || ssoSessionId.isBlank()) { if (ssoSessionId == null || ssoSessionId.isBlank()) {
return; return;
} }
@@ -0,0 +1,27 @@
package com.alist.api.modules.auth.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Schema(description = "SSO 기반 토큰 발급 응답")
@Getter
@Setter
public class AuthAccessVo {
@JsonProperty("isAccessToken")
@Schema(description = "Access Token 발급 여부", example = "true")
private boolean accessToken;
@Schema(description = "회원 PK", example = "1")
private Integer userIdx;
@Schema(description = "회원 아이디", example = "test")
private String userId;
@Schema(description = "회원 권한 코드", example = "CCD/SCM/I/R/E")
private String userRole;
@Schema(description = "회원 유형 코드. T: 교사, S: 학생", example = "S")
private String userType;
}
@@ -0,0 +1,24 @@
package com.alist.api.modules.auth.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Schema(description = "API Key 로그인 응답")
@Getter
@Setter
public class AuthApiKeyLoginVo {
@Schema(description = "아이디")
private String id;
@Schema(description = "엑세스 토큰")
private String accessToken;
@Schema(description = "리플레시 토큰")
private String refreshToken;
@JsonIgnore
@Schema(hidden = true)
private int resultCode;
}
@@ -0,0 +1,22 @@
package com.alist.api.modules.auth.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Schema(description = "Access Token 재발급 응답")
@Getter
@Setter
public class AuthRefreshVo {
@Schema(description = "토큰 재발급 여부", example = "true")
private boolean refreshed;
@JsonIgnore
@Schema(hidden = true)
private String accessToken;
@JsonIgnore
@Schema(hidden = true)
private String refreshToken;
}
@@ -1,20 +1,20 @@
package com.alist.api.modules.auth.dto; package com.alist.api.modules.auth.vo;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import java.time.Instant;
@Schema(description = "테스트용 토큰 발급 응답") @Schema(description = "테스트용 토큰 발급 응답")
@Getter @Getter
@Setter @Setter
public class TokenDto { public class AuthTokenVo {
@Schema(description = "아이디") @Schema(description = "아이디")
private String id; private String id;
@Schema(description = "엑세스 토큰") @Schema(description = "엑세스 토큰")
private String accessToken; private String accessToken;
@Schema(description = "리플레시 토큰") @Schema(description = "리플레시 토큰")
private String refreshToken; private String refreshToken;
@@ -1,10 +1,22 @@
package com.alist.api.modules.auth.vo; package com.alist.api.modules.auth.vo;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
import java.time.Instant;
@Getter @Getter
@Setter
public class LoginVo { public class LoginVo {
private Integer userIdx; private Integer userIdx;
private String id; private String id;
private String password; private String password;
private String accessToken;
private String refreshToken;
private Integer userTokenIdx;
private String userRole;
private String userType;
private Instant expiresAt;
private int resultCode;
} }
@@ -0,0 +1,34 @@
package com.alist.api.modules.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Schema(description = "SSO 인가 코드 교환 응답")
@Getter
@Setter
public class SsoExchangeVo {
@Schema(description = "SSO 인가 코드", example = "authorization-code")
private String code;
@Schema(description = "SSO 클라이언트 ID", example = "alist-main")
private String clientId;
@Schema(description = "SSO 세션 ID")
private String ssoSessionId;
@Schema(description = "회원 PK", example = "1")
private Integer userIdx;
@Schema(description = "회원 토큰 PK", example = "1")
private Integer userTokenIdx;
@Schema(description = "회원 아이디", example = "test")
private String userId;
@Schema(description = "회원 권한 코드(CCD/SCM/I/R/E)", example = "SCM")
private String userRole;
@Schema(description = "회원 유형 코드. T: 교사, S: 학생", example = "T")
private String userType;
}
@@ -0,0 +1,40 @@
package com.alist.api.modules.auth.vo;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Schema(description = "SSO 로그인 상태 확인 응답")
@Getter
@Setter
public class SsoLoginCheckedVo {
@JsonProperty("isAccessToken")
@Schema(description = "Access Token 쿠키 존재 여부", example = "true")
private boolean accessToken;
@JsonProperty("isRefreshToken")
@Schema(description = "Refresh Token 쿠키 존재 여부", example = "true")
private boolean refreshToken;
@Schema(description = "로그인 상태 여부", example = "true")
private boolean loggedIn;
@Schema(description = "SSO 세션 ID")
private String ssoSessionId;
@Schema(description = "회원 아이디", example = "test")
private String userId;
@Schema(description = "회원 PK", example = "1")
private Integer userIdx;
@Schema(description = "회원 토큰 PK", example = "1")
private Integer userTokenIdx;
@Schema(description = "회원 권한 코드", example = "CCD/SCM/I/R/E")
private String userRole;
@Schema(description = "회원 유형 코드. T: 교사, S: 학생", example = "S")
private String userType;
}
@@ -1,5 +1,6 @@
package com.alist.api.modules.auth.dto; package com.alist.api.modules.auth.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@@ -7,7 +8,7 @@ import lombok.Setter;
@Schema(description = "SSO 로그인 응답") @Schema(description = "SSO 로그인 응답")
@Getter @Getter
@Setter @Setter
public class SsoLoginCheckDto { public class SsoLoginVo {
@Schema(description = "로그인 성공 여부", example = "true") @Schema(description = "로그인 성공 여부", example = "true")
private boolean loginIn; private boolean loginIn;
@@ -22,4 +23,20 @@ public class SsoLoginCheckDto {
@Schema(description = "회원 유형 코드. T: 교사, S: 학생", example = "S") @Schema(description = "회원 유형 코드. T: 교사, S: 학생", example = "S")
private String userType; private String userType;
@JsonIgnore
@Schema(hidden = true)
private String ssoSessionId;
@JsonIgnore
@Schema(hidden = true)
private Integer userTokenIdx;
@JsonIgnore
@Schema(hidden = true)
private String userId;
@JsonIgnore
@Schema(hidden = true)
private int resultCode;
} }
@@ -0,0 +1,13 @@
package com.alist.api.modules.auth.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Schema(description = "SSO 로그아웃 응답")
@Getter
@Setter
public class SsoLogoutVo {
@Schema(description = "로그아웃 처리 여부", example = "true")
private boolean logout;
}
@@ -1,22 +0,0 @@
package com.alist.api.modules.auth.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;
import lombok.Setter;
@Schema(description = "테스트용 토큰 발급 응답")
@Getter
@Setter
public class TokenVo {
@Schema(description = "아이디")
private String id;
@Schema(description = "엑세스 토큰")
private String accessToken;
@Schema(description = "리플레시 토큰")
private String refreshToken;
@JsonIgnore
@Schema(hidden = true)
private int resultCode;
}
@@ -67,7 +67,7 @@
/*LoginMapper.updateLoginByLastAt*/ /*LoginMapper.updateLoginByLastAt*/
update ALISTLMS.test_user update ALISTLMS.test_user
set last_login_at = now() set last_login_at = now()
, update_at = now() , update_at = now()
where user_idx = #{userIdx} where user_idx = #{userIdx}
</update> </update>
</mapper> </mapper>