Skip to content

Commit

Permalink
feat: 로그인 controller, service 구현
Browse files Browse the repository at this point in the history
related to: #11
  • Loading branch information
heejjinkim committed Sep 3, 2024
1 parent 1883a81 commit 26faf60
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 0 deletions.
58 changes: 58 additions & 0 deletions src/main/java/com/_119/wepro/auth/presentation/AuthController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com._119.wepro.auth.presentation;

import com._119.wepro.auth.dto.response.AuthResponse.SignInResponse;
import com._119.wepro.auth.service.KakaoService;
import com._119.wepro.auth.service.SignInService;
import com._119.wepro.auth.dto.request.AuthRequest.*;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.view.RedirectView;

@Slf4j
@RequiredArgsConstructor
@RestController
public class AuthController {

private final KakaoService kakaoService;
private final SignInService signInService;

@PostMapping("/login")
@Operation(summary = "Kakao idToken 받아 소셜 로그인")
public ResponseEntity<SignInResponse> signIn(
@RequestBody @Valid SignInRequest request) {
return ResponseEntity.ok(signInService.signIn(request));
}

@PostMapping("/signup")
@Operation(summary = "직군 정보 받아 최종 회원가입")
public ResponseEntity<Void> register(
@RequestBody @Valid SignUpRequest request) {
return ResponseEntity.ok().build();
}

@GetMapping("/auth/kakao")
@Operation(summary = "Kakao Web 소셜 로그인 용 api, 백엔드용")
public RedirectView kakaoLogin() {
return new RedirectView(kakaoService.generateKakaoRedirectUrl());
}

@GetMapping("/login/oauth2/code/kakao")
@Operation(summary = "카카오 code 받는 api, 백엔드용")
public SignInResponse handleKakaoCallback(@RequestParam String code) {
return kakaoService.handleKakaoCallback(code);
}

@GetMapping("/test")
public void test(Authentication authentication) {
log.info(authentication.getName());
}
}
75 changes: 75 additions & 0 deletions src/main/java/com/_119/wepro/auth/service/SignInService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com._119.wepro.auth.service;

import static com._119.wepro.global.enums.Provider.APPLE;
import static com._119.wepro.global.enums.Provider.KAKAO;

import com._119.wepro.auth.dto.response.AuthResponse.SignInResponse;
import com._119.wepro.auth.dto.response.TokenInfo;
import com._119.wepro.global.enums.Provider;
import com._119.wepro.global.enums.Role;
import com._119.wepro.auth.jwt.JwtTokenProvider;
import com._119.wepro.member.domain.Member;
import com._119.wepro.member.domain.repository.MemberRepository;
import com._119.wepro.auth.dto.request.AuthRequest.SignInRequest;
import jakarta.transaction.Transactional;
import java.util.Map;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.stereotype.Service;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.core.oidc.OidcIdToken;


@Slf4j
@Service
@RequiredArgsConstructor
public class SignInService {

private final MemberRepository memberRepository;
private final JwtTokenProvider jwtTokenProvider;

private final Map<Provider, JwtDecoder> decoders = Map.of(
Provider.KAKAO, buildDecoder(KAKAO.getJwkSetUrl()),
Provider.APPLE, buildDecoder(APPLE.getJwkSetUrl()));

private JwtDecoder buildDecoder(String jwkUrl) {
return NimbusJwtDecoder.withJwkSetUri(jwkUrl).build();
}

@Transactional
public SignInResponse signIn(SignInRequest request) {
OidcUser oidcDecodePayload = socialLogin(request);

Member member = getOrSaveUser(request, oidcDecodePayload);
TokenInfo tokenInfo = jwtTokenProvider.generateToken(member.getId(), member.getRole());
boolean isNewMember = Role.GUEST == member.getRole();

return new SignInResponse(isNewMember, tokenInfo);
}


private Member getOrSaveUser(SignInRequest request, OidcUser oidcDecodePayload) {
Optional<Member> member = memberRepository.findByProviderAndProviderId(
request.getProvider(), oidcDecodePayload.getName());

return member.orElseGet(
() -> memberRepository.save(Member.of(request, oidcDecodePayload)));

}

private OidcUser socialLogin(SignInRequest request) {
Provider provider = request.getProvider();

Jwt jwt = decoders.get(provider).decode(request.getIdToken());
OidcIdToken oidcIdToken = new OidcIdToken(
jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt(), jwt.getClaims());

return new DefaultOidcUser(null, oidcIdToken);
// throw new RestApiException(UNSUPPORTED_PROVIDER);
}
}

0 comments on commit 26faf60

Please sign in to comment.