Skip to content
Merged
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
@@ -0,0 +1,50 @@
package com.gltkorea.icebang.auth.controller;

import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
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;

import com.gltkorea.icebang.auth.dto.DefaultRequestWrapper;
import com.gltkorea.icebang.auth.dto.LoginDto;
import com.gltkorea.icebang.auth.dto.SignUpDto;
import com.gltkorea.icebang.auth.provider.AuthProvider;
import com.gltkorea.icebang.auth.provider.AuthProviderFactory;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/v0/auth")
public class AuthController {
private final AuthProviderFactory authProviderFactory;

@PostMapping("/signup")
public ResponseEntity<?> signUp(@RequestBody SignUpDto signUpDto) {
// 1. Wrapper DTO 생성
DefaultRequestWrapper wrapper = DefaultRequestWrapper.builder().signUpDto(signUpDto).build();

// 2. Factory에서 Provider 선택
@SuppressWarnings("unchecked")
AuthProvider<DefaultRequestWrapper> provider =
(AuthProvider<DefaultRequestWrapper>) authProviderFactory.getProvider("default");

// 3. Provider에 인증 위임 (Provider 내부에서 signUp + login 처리)
Authentication auth = provider.authenticate(wrapper);

// 4. 결과 반환
return ResponseEntity.status(201).body(auth);
}

@PostMapping("/signin")
public ResponseEntity<?> signIn(@RequestBody LoginDto loginDto) {
DefaultRequestWrapper wrapper = DefaultRequestWrapper.builder().loginDto(loginDto).build();
@SuppressWarnings("unchecked")
AuthProvider<DefaultRequestWrapper> provider =
(AuthProvider<DefaultRequestWrapper>) authProviderFactory.getProvider("default");
Authentication auth = provider.authenticate(wrapper);
return ResponseEntity.ok(auth);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.gltkorea.icebang.auth.controller;

import org.springframework.web.bind.annotation.*;

import lombok.RequiredArgsConstructor;

@RestController
@RequestMapping("/v0/oauth2/callback")
@RequiredArgsConstructor
public class Oauth2CallbackController {

@GetMapping("/kakao")
public void handleKakaoCallback(@RequestParam String code) {
// OAuth2RequestWrapper wrapper = new OAuth2RequestWrapper(new
// Oauth2CallbackContent("kakao", code));
// OAuth2AuthProvider provider = (OAuth2AuthProvider)
// authProviderFactory.getProvider(providerKey);
// Authentication auth = provider.authenticate(wrapper);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.gltkorea.icebang.auth.dto;

public interface AuthRequestWrapper {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.gltkorea.icebang.auth.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Builder
@AllArgsConstructor
@Getter
public class DefaultRequestWrapper implements AuthRequestWrapper {
private final LoginDto loginDto;
private final SignUpDto signUpDto;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.gltkorea.icebang.auth.dto;

public class LoginDto {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.gltkorea.icebang.auth.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
@AllArgsConstructor
public class OAuth2RequestWrapper implements AuthRequestWrapper {
private Oauth2CallbackContent callbackContent;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.gltkorea.icebang.auth.dto;

public class Oauth2CallbackContent {
private String code;
private String state;
private String provider;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.gltkorea.icebang.auth.dto;

public class SignUpDto {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.gltkorea.icebang.auth.provider;

import org.springframework.security.core.Authentication;

import com.gltkorea.icebang.auth.dto.AuthRequestWrapper;

public interface AuthProvider<T extends AuthRequestWrapper> {
boolean supports(T request);

Authentication authenticate(T request);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.gltkorea.icebang.auth.provider;

import java.util.Map;

import org.springframework.stereotype.Component;

import com.gltkorea.icebang.auth.dto.AuthRequestWrapper;

import lombok.RequiredArgsConstructor;

@Component
@RequiredArgsConstructor
public class AuthProviderFactory {

private final Map<String, AuthProvider<? extends AuthRequestWrapper>> providers;

/**
* providerKey에 해당하는 AuthProvider 반환
*
* @param providerKey "google", "naver", "default" 등, enum으로 refactoring 필요
* @return AuthProvider
*/
public AuthProvider<? extends AuthRequestWrapper> getProvider(String providerKey) {
AuthProvider<? extends AuthRequestWrapper> provider = providers.get(providerKey.toLowerCase());
if (provider == null) {
throw new IllegalArgumentException("Unknown auth provider: " + providerKey);
}
return provider;
}

/**
* OAuth2 전용 Provider 반환
*
* @param providerKey OAuth2 provider key
* @return OAuth2AuthProvider
*/
public OAuth2AuthProvider getOAuth2Provider(String providerKey) {
AuthProvider<? extends AuthRequestWrapper> provider = getProvider(providerKey);
if (!(provider instanceof OAuth2AuthProvider oauthProvider)) {
throw new IllegalArgumentException(providerKey + " is not an OAuth2 provider");
}
return oauthProvider;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.gltkorea.icebang.auth.provider;

import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import com.gltkorea.icebang.auth.dto.DefaultRequestWrapper;

@Component("default")
public class DefaultProvider implements AuthProvider<DefaultRequestWrapper> {
@Override
public boolean supports(DefaultRequestWrapper request) {
return false;
}

@Override
public Authentication authenticate(DefaultRequestWrapper request) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.gltkorea.icebang.auth.provider;

import org.springframework.security.core.Authentication;

import com.gltkorea.icebang.auth.dto.OAuth2RequestWrapper;

public interface OAuth2AuthProvider extends AuthProvider<OAuth2RequestWrapper> {
Authentication authenticateWithCode(OAuth2RequestWrapper oauthContent);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.gltkorea.icebang.auth.service;

import com.gltkorea.icebang.auth.dto.LoginDto;
import com.gltkorea.icebang.auth.dto.SignUpDto;
import com.gltkorea.icebang.domain.user.model.Users;

public interface AuthService {
Users signUp(SignUpDto signUpDto);

Users login(LoginDto loginDto);

Users loadUser(String identifier);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.gltkorea.icebang.auth.service;

import org.springframework.stereotype.Service;

import com.gltkorea.icebang.auth.dto.LoginDto;
import com.gltkorea.icebang.auth.dto.SignUpDto;
import com.gltkorea.icebang.domain.user.model.Users;

@Service
public class AuthServiceImpl implements AuthService {
@Override
public Users signUp(SignUpDto signUpDto) {
return null;
}

@Override
public Users login(LoginDto loginDto) {
return null;
}

@Override
public Users loadUser(String identifier) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.gltkorea.icebang.auth.service.state;

import org.springframework.security.core.userdetails.UserDetails;

public sealed interface AuthStateService permits SessionStateService, JwtTokenStateService {
String create(UserDetails userDetails);

UserDetails validate(String identifier);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.gltkorea.icebang.auth.service.state;

import org.springframework.security.core.userdetails.UserDetails;

public final class JwtTokenStateService implements AuthStateService {
@Override
public String create(UserDetails userDetails) {
return "";
}

@Override
public UserDetails validate(String identifier) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.gltkorea.icebang.auth.service.state;

import org.springframework.security.core.userdetails.UserDetails;

public final class SessionStateService implements AuthStateService {
@Override
public String create(UserDetails userDetails) {
return "";
}

@Override
public UserDetails validate(String identifier) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.gltkorea.icebang.domain.user;

public enum UserStatus {
ONBOARDING, // email, password만 된 경우
ACTIVE, // 완전히 활성화됨
SUSPENDED, // 일시 정지
DELETED // 삭제됨
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.gltkorea.icebang.domain.user.model;

import com.gltkorea.icebang.domain.user.UserStatus;

public class Users {
private UserStatus status;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.gltkorea.icebang.auth.service.AuthService;
import com.gltkorea.icebang.domain.user.model.UserAccountPrincipal;
import com.gltkorea.icebang.domain.user.model.Users;

public class SecurityAuthenticateAdapter implements UserAuthService {
private AuthService authService;

public class UserAuthServiceImpl implements UserAuthService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return UserAccountPrincipal.builder().build();
Users user = authService.loadUser(username);
return UserAccountPrincipal.builder().build(); // @TODO users -> userdetail로
}
}