Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat/CK-241] 회원, 인증/인가, 공통 부분 의존성 리펙토링을 한다 #209

Merged
merged 6 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
4 changes: 3 additions & 1 deletion backend/kirikiri/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ jacocoTestReport {
fileTree(dir: it, excludes: [
"co/kirikiri/persistence/QuerydslRepositorySupporter",
"co/kirikiri/domain/**",
"co/kirikiri/**/domain/**",
"co/kirikiri/persistence/goalroom/dto/**",
"**/*Application*",
"**/*Config*",
Expand Down Expand Up @@ -115,7 +116,8 @@ jacocoTestCoverageVerification {

excludes = [
"co.kirikiri.persistence.QuerydslRepositorySupporter",
"co.kirikiri.domain.**.**",
"co.kirikiri.domain.**",
"co.kirikiri.**.domain.**",
"co.kirikiri.persistence.goalroom.dto.**",
"**.*Application*",
"**.*Config*",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package co.kirikiri.controller;
package co.kirikiri.auth.controller;

import co.kirikiri.service.auth.AuthService;
import co.kirikiri.service.auth.NaverOauthService;
import co.kirikiri.service.dto.auth.OauthRedirectResponse;
import co.kirikiri.service.dto.auth.request.LoginRequest;
import co.kirikiri.service.dto.auth.request.ReissueTokenRequest;
import co.kirikiri.service.dto.auth.response.AuthenticationResponse;
import co.kirikiri.auth.service.AuthService;
import co.kirikiri.auth.service.NaverOauthService;
import co.kirikiri.auth.service.dto.response.OauthRedirectResponse;
import co.kirikiri.auth.service.dto.request.LoginRequest;
import co.kirikiri.auth.service.dto.request.ReissueTokenRequest;
import co.kirikiri.auth.service.dto.response.AuthenticationResponse;
import jakarta.validation.Valid;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -15,7 +16,6 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;

@RestController
@RequestMapping("/auth")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package co.kirikiri.infra;
package co.kirikiri.auth.infra;

import co.kirikiri.service.OauthNetworkService;
import co.kirikiri.auth.service.OauthNetworkService;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpEntity;
Expand All @@ -9,7 +10,6 @@
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Map;

@Service
@RequiredArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package co.kirikiri.auth.interceptor;

import co.kirikiri.auth.service.AuthService;
import co.kirikiri.common.exception.AuthenticationException;
import co.kirikiri.common.interceptor.AuthInterceptor;
import co.kirikiri.common.interceptor.Authenticated;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;

@Component
@RequiredArgsConstructor
public class AuthInterceptorImpl implements AuthInterceptor {

private static final String BEARER = "Bearer ";

private final AuthService authService;

@Override
public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response,
final Object handler) {
if (!(handler instanceof final HandlerMethod handlerMethod)) {
return true;
}
if (handlerMethod.hasMethodAnnotation(Authenticated.class)) {
final String authorizationHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
checkHeader(authorizationHeader);
final String token = authorizationHeader.substring(BEARER.length());
checkTokenCertify(token);
}
return true;
}

private void checkHeader(final String authorizationHeader) {
if (authorizationHeader == null || !authorizationHeader.startsWith(BEARER)) {
throw new AuthenticationException("인증 헤더가 적절하지 않습니다.");
}
}

private void checkTokenCertify(final String token) {
if (!authService.isCertified(token)) {
throw new AuthenticationException("토큰이 유효하지 않습니다.");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package co.kirikiri.persistence.auth;
package co.kirikiri.auth.persistence;

import java.util.Optional;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package co.kirikiri.persistence.auth;
package co.kirikiri.auth.persistence;

import java.util.Optional;
import java.util.concurrent.TimeUnit;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package co.kirikiri.auth.resolver;

import co.kirikiri.auth.service.AuthService;
import co.kirikiri.common.exception.AuthenticationException;
import co.kirikiri.common.exception.ServerException;
import co.kirikiri.common.interceptor.Authenticated;
import co.kirikiri.common.resolver.MemberIdentifier;
import co.kirikiri.common.resolver.MemberIdentifierArgumentResolver;
import lombok.RequiredArgsConstructor;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;

@Component
@RequiredArgsConstructor
public class MemberIdentifierArgumentResolverImpl implements MemberIdentifierArgumentResolver {

private static final String BEARER = "Bearer ";

private final AuthService authService;

@Override
public boolean supportsParameter(final MethodParameter parameter) {
if (!parameter.hasMethodAnnotation(Authenticated.class)) {
throw new ServerException("MemberIdentifier는 인증된 사용자만 사용 가능합니다. (@Authenticated)");
}
return parameter.getParameterType().equals(String.class)
&& parameter.hasParameterAnnotation(MemberIdentifier.class);
}

@Override
public String resolveArgument(final MethodParameter parameter, final ModelAndViewContainer mavContainer,
final NativeWebRequest webRequest, final WebDataBinderFactory binderFactory) {
final String authorizationHeader = webRequest.getHeader(HttpHeaders.AUTHORIZATION);
checkHeader(authorizationHeader);
final String token = authorizationHeader.substring(BEARER.length());
return authService.findIdentifierByToken(token);
}

private void checkHeader(final String authorizationHeader) {
if (authorizationHeader == null || !authorizationHeader.startsWith(BEARER)) {
throw new AuthenticationException("인증 헤더가 적절하지 않습니다.");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package co.kirikiri.service.auth;
package co.kirikiri.auth.service;

import co.kirikiri.domain.member.Member;
import co.kirikiri.domain.member.vo.Identifier;
import co.kirikiri.domain.member.vo.Password;
import co.kirikiri.persistence.auth.RefreshTokenRepository;
import co.kirikiri.persistence.member.MemberRepository;
import co.kirikiri.service.aop.ExceptionConvert;
import co.kirikiri.service.dto.auth.LoginDto;
import co.kirikiri.service.dto.auth.request.LoginRequest;
import co.kirikiri.service.dto.auth.request.ReissueTokenRequest;
import co.kirikiri.service.dto.auth.response.AuthenticationResponse;
import co.kirikiri.service.exception.AuthenticationException;
import co.kirikiri.service.mapper.AuthMapper;
import co.kirikiri.auth.persistence.RefreshTokenRepository;
import co.kirikiri.auth.service.dto.LoginDto;
import co.kirikiri.auth.service.dto.request.LoginRequest;
import co.kirikiri.auth.service.dto.request.ReissueTokenRequest;
import co.kirikiri.auth.service.dto.response.AuthenticationResponse;
import co.kirikiri.auth.service.mapper.AuthMapper;
import co.kirikiri.common.aop.ExceptionConvert;
import co.kirikiri.common.exception.AuthenticationException;
import co.kirikiri.member.domain.Member;
import co.kirikiri.member.domain.vo.Identifier;
import co.kirikiri.member.domain.vo.Password;
import co.kirikiri.member.persistence.MemberRepository;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package co.kirikiri.service.auth;
package co.kirikiri.auth.service;

import co.kirikiri.service.exception.AuthenticationException;
import co.kirikiri.common.exception.AuthenticationException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jws;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
package co.kirikiri.service.auth;
package co.kirikiri.auth.service;

import co.kirikiri.domain.member.Member;
import co.kirikiri.persistence.member.MemberRepository;
import co.kirikiri.service.OauthNetworkService;
import co.kirikiri.service.dto.auth.NaverMemberProfileDto;
import co.kirikiri.service.dto.auth.NaverMemberProfileResponseDto;
import co.kirikiri.service.dto.auth.NaverOauthTokenDto;
import co.kirikiri.service.dto.auth.OauthRedirectResponse;
import co.kirikiri.service.dto.auth.response.AuthenticationResponse;
import co.kirikiri.service.dto.member.OauthMemberJoinDto;
import co.kirikiri.service.dto.member.request.GenderType;
import co.kirikiri.service.mapper.OauthMapper;
import co.kirikiri.service.member.MemberService;
import co.kirikiri.auth.service.dto.NaverMemberProfileDto;
import co.kirikiri.auth.service.dto.NaverMemberProfileResponseDto;
import co.kirikiri.auth.service.dto.NaverOauthTokenDto;
import co.kirikiri.auth.service.dto.response.OauthRedirectResponse;
import co.kirikiri.auth.service.dto.response.AuthenticationResponse;
import co.kirikiri.auth.service.mapper.OauthMapper;
import co.kirikiri.member.domain.Member;
import co.kirikiri.member.persistence.MemberRepository;
import co.kirikiri.member.service.MemberService;
import co.kirikiri.member.service.dto.OauthMemberJoinDto;
import co.kirikiri.member.service.dto.request.GenderType;
import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Map;
Expand Down Expand Up @@ -58,17 +57,19 @@ private String getProperty(final String property) {

@Transactional
public AuthenticationResponse login(final Map<String, String> queryParams) {
final NaverOauthTokenDto naverOauthTokenDto = oauthNetworkService.requestToken(NaverOauthTokenDto.class,
queryParams).getBody();
final NaverOauthTokenDto naverOauthTokenDto = oauthNetworkService.requestToken(NaverOauthTokenDto.class, queryParams)
.getBody();
final NaverMemberProfileDto naverMemberProfileDto = getNaverMemberProfileDto(naverOauthTokenDto.accessToken());
final NaverMemberProfileResponseDto naverMemberProfileResponseDto = naverMemberProfileDto.response();
final Optional<Member> optionalMember = memberRepository.findByOauthId(naverMemberProfileResponseDto.id());
if (optionalMember.isPresent()) {
final Member member = optionalMember.get();
return authService.oauthLogin(member);
}
final Member savedMember = optionalMember.orElseGet(() -> saveMember(naverMemberProfileResponseDto));
return authService.oauthLogin(savedMember);
}

private Member saveMember(final NaverMemberProfileResponseDto naverMemberProfileResponseDto) {
return memberService.oauthJoin(
new OauthMemberJoinDto(naverMemberProfileResponseDto.id(), naverMemberProfileResponseDto.email(),
new OauthMemberJoinDto(naverMemberProfileResponseDto.id(),
naverMemberProfileResponseDto.email(),
naverMemberProfileResponseDto.nickname(),
GenderType.findByOauthType(naverMemberProfileResponseDto.gender())));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package co.kirikiri.service;
package co.kirikiri.auth.service;

import org.springframework.http.ResponseEntity;
import java.util.Map;
import org.springframework.http.ResponseEntity;

public interface OauthNetworkService {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package co.kirikiri.service.auth;
package co.kirikiri.auth.service;

import java.time.LocalDateTime;
import java.util.Map;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package co.kirikiri.auth.service.dto;

import co.kirikiri.member.domain.vo.Identifier;
import co.kirikiri.member.domain.vo.Password;

public record LoginDto(
Identifier identifier,
Password password
) {

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package co.kirikiri.service.dto.auth;
package co.kirikiri.auth.service.dto;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package co.kirikiri.service.dto.auth;
package co.kirikiri.auth.service.dto;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package co.kirikiri.service.dto.auth;
package co.kirikiri.auth.service.dto;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package co.kirikiri.service.dto.auth.request;
package co.kirikiri.auth.service.dto.request;

import jakarta.validation.constraints.NotBlank;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package co.kirikiri.service.dto.auth.request;
package co.kirikiri.auth.service.dto.request;

import jakarta.validation.constraints.NotBlank;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package co.kirikiri.service.dto.auth.response;
package co.kirikiri.auth.service.dto.response;

public record AuthenticationResponse(
String refreshToken,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package co.kirikiri.service.dto.auth;
package co.kirikiri.auth.service.dto.response;

public record OauthRedirectResponse(
String url,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package co.kirikiri.service.mapper;
package co.kirikiri.auth.service.mapper;

import co.kirikiri.domain.member.vo.Identifier;
import co.kirikiri.domain.member.vo.Password;
import co.kirikiri.service.dto.auth.LoginDto;
import co.kirikiri.service.dto.auth.request.LoginRequest;
import co.kirikiri.service.dto.auth.response.AuthenticationResponse;
import co.kirikiri.auth.service.dto.LoginDto;
import co.kirikiri.auth.service.dto.request.LoginRequest;
import co.kirikiri.auth.service.dto.response.AuthenticationResponse;
import co.kirikiri.member.domain.vo.Identifier;
import co.kirikiri.member.domain.vo.Password;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package co.kirikiri.service.mapper;
package co.kirikiri.auth.service.mapper;

import co.kirikiri.service.dto.auth.OauthRedirectResponse;
import co.kirikiri.auth.service.dto.response.OauthRedirectResponse;

public class OauthMapper {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package co.kirikiri.service.aop;
package co.kirikiri.common.aop;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package co.kirikiri.service.aop;
package co.kirikiri.common.aop;

import co.kirikiri.domain.exception.DomainException;
import co.kirikiri.domain.exception.UnexpectedDomainException;
import co.kirikiri.service.exception.BadRequestException;
import co.kirikiri.service.exception.ServerException;
import co.kirikiri.common.exception.BadRequestException;
import co.kirikiri.common.exception.domain.DomainException;
import co.kirikiri.common.exception.ServerException;
import co.kirikiri.common.exception.domain.UnexpectedDomainException;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
Expand All @@ -12,7 +12,7 @@
@Component
public class ExceptionConvertAop {

@AfterThrowing(pointcut = "within(@co.kirikiri.service.aop.ExceptionConvert *)", throwing = "exception")
@AfterThrowing(pointcut = "within(@co.kirikiri.common.aop.ExceptionConvert *)", throwing = "exception")
public void convertException(final Throwable exception) {
if (exception instanceof UnexpectedDomainException) {
throw new ServerException(exception.getMessage());
Expand Down
Loading
Loading