Skip to content

Commit

Permalink
Merge branch 'feature/socialLogin' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Anna-Jin committed Jul 15, 2022
2 parents 25100a9 + 8224362 commit a559346
Show file tree
Hide file tree
Showing 36 changed files with 205 additions and 181 deletions.
7 changes: 0 additions & 7 deletions src/main/java/com/mpnp/baechelin/BaechelinApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,12 @@

import com.mpnp.baechelin.config.properties.AppProperties;
import com.mpnp.baechelin.config.properties.CorsProperties;
import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.*;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import reactor.netty.http.client.HttpClient;

import java.time.Duration;
import java.util.concurrent.TimeUnit;


@EnableJpaAuditing
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

import com.mpnp.baechelin.config.properties.AppProperties;
import com.mpnp.baechelin.config.properties.CorsProperties;
import com.mpnp.baechelin.oauth.entity.RoleType;
import com.mpnp.baechelin.oauth.exception.RestAuthenticationEntryPoint;
import com.mpnp.baechelin.oauth.filter.TokenAuthenticationFilter;
import com.mpnp.baechelin.oauth.handler.OAuth2AuthenticationFailureHandler;
import com.mpnp.baechelin.oauth.handler.OAuth2AuthenticationSuccessHandler;
import com.mpnp.baechelin.oauth.handler.TokenAccessDeniedHandler;
import com.mpnp.baechelin.oauth.repository.OAuth2AuthorizationRequestBasedOnCookieRepository;
import com.mpnp.baechelin.oauth.service.CustomOAuth2UserService;
import com.mpnp.baechelin.oauth.token.AuthTokenProvider;
import com.mpnp.baechelin.user.repository.UserRefreshTokenRepository;
import com.mpnp.baechelin.login.oauth.entity.RoleType;
import com.mpnp.baechelin.login.jwt.exception.RestAuthenticationEntryPoint;
import com.mpnp.baechelin.login.jwt.filter.TokenAuthenticationFilter;
import com.mpnp.baechelin.login.oauth.handler.OAuth2AuthenticationFailureHandler;
import com.mpnp.baechelin.login.oauth.handler.OAuth2AuthenticationSuccessHandler;
import com.mpnp.baechelin.login.jwt.handler.TokenAccessDeniedHandler;
import com.mpnp.baechelin.login.oauth.repository.OAuth2AuthorizationRequestBasedOnCookieRepository;
import com.mpnp.baechelin.login.oauth.service.CustomOAuth2UserService;
import com.mpnp.baechelin.login.jwt.AuthTokenProvider;
import com.mpnp.baechelin.login.jwt.repository.UserRefreshTokenRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/com/mpnp/baechelin/exception/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.mpnp.baechelin.exception;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum ErrorCode {

SUCCESS_MESSAGE(200, "S-SUC200","SUCCESS"),
// NOT_FOUND_MESSAGE(500, "BE001", "NOT FOUND"),
FAILED_MESSAGE(500, "E-FAI500","서버에서 오류가 발생하였습니다."),
INVALID_ACCESS_TOKEN(401, "E-IAT401","유효하지 않은 Access Token입니다."),
INVALID_REFRESH_TOKEN(401, "E-IRT401", "유효하지 않은 Refresh Token입니다."),
NOT_EXPIRED_TOKEN_YET(401, "E-NET401", "만료되지 않은 JWT 토큰입니다."),
EXPIRED_TOKEN(401, "E-EXT401", "만료된 JWT 토큰입니다."),
WRONG_TYPE_TOKEN(401, "E-WTT401","잘못된 JWT 토큰입니다."),
WRONG_TYPE_SIGNATURE(401, "E-WTS401", "잘못된 JWT 서명입니다."),
ACCESS_DENIED(401, "E-ACD401","접근이 거부되었습니다."),
TOKEN_NOT_EXIST(401, "E-TNE401", "토큰이 존재하지 않습니다."),
ALREADY_LOGIN_ACCOUNT(400, "E-ALA400","다른 계정으로 로그인 되었습니다.");

private final int status;
private final String code;
private final String message;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.mpnp.baechelin.oauth.token;
package com.mpnp.baechelin.login.jwt;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.SignatureException;
Expand Down Expand Up @@ -48,10 +48,16 @@ private String createAuthToken(String id, String role, Date expiry) {
.compact();
}

public boolean validate() {
return this.getTokenClaims() != null;
// 토큰 유효성 검사
public boolean tokenValidate() {
Jws<Claims> claimsJws = Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token);
return !claimsJws.getBody().isEmpty();
}


// 토큰의 claims, payload 값 가져오기
public Claims getTokenClaims() {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.mpnp.baechelin.oauth.token;
package com.mpnp.baechelin.login.jwt;

import com.mpnp.baechelin.oauth.exception.TokenValidFailedException;
import com.mpnp.baechelin.login.jwt.exception.TokenValidFailedException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -46,7 +46,7 @@ public AuthToken convertAuthToken(String token) {
// 인증 객체 생성
public Authentication getAuthentication(AuthToken authToken) {
// 유효한 토큰일 때
if (authToken.validate()) {
if (authToken.tokenValidate()) {
Claims claims = authToken.getTokenClaims();
Collection<? extends GrantedAuthority> authorities =
Arrays.stream(new String[] {claims.get(AUTHORITIES_KEY).toString()})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.mpnp.baechelin.config.security;
package com.mpnp.baechelin.login.jwt.config;

import com.mpnp.baechelin.oauth.token.AuthTokenProvider;
import com.mpnp.baechelin.login.jwt.AuthTokenProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.mpnp.baechelin.oauth.controller;
package com.mpnp.baechelin.login.jwt.controller;

import com.mpnp.baechelin.oauth.common.AuthResponse;
import com.mpnp.baechelin.oauth.service.AuthService;
import com.mpnp.baechelin.login.oauth.common.AuthResponse;
import com.mpnp.baechelin.login.jwt.service.TokenService;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -14,13 +14,13 @@
@RestController
@RequestMapping("/auth")
@RequiredArgsConstructor
public class AuthController {
public class TokenController {

private final AuthService authService;
private final TokenService tokenService;

@ApiOperation(value = "Access Token 만료 시 Refresh Token을 이용하여 재발급 받는 메소드")
@GetMapping("/refresh")
public AuthResponse refreshToken (HttpServletRequest request, HttpServletResponse response) {
return authService.refreshToken(request, response);
return tokenService.refreshToken(request, response);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.mpnp.baechelin.user.domain;
package com.mpnp.baechelin.login.jwt.entity;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Builder;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.mpnp.baechelin.oauth.exception;
package com.mpnp.baechelin.login.jwt.exception;

import com.google.gson.JsonObject;
import com.mpnp.baechelin.exception.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
Expand All @@ -20,7 +20,7 @@ public void commence(
HttpServletResponse response,
AuthenticationException authException
) throws IOException {
String exception = (String)request.getAttribute("javax.servlet.error.exception");
String exception = (String)request.getAttribute("exception");

if(exception == null) {
setResponse(response, ErrorCode.FAILED_MESSAGE);
Expand All @@ -29,12 +29,15 @@ public void commence(
else if(exception.equals(ErrorCode.WRONG_TYPE_TOKEN.getCode())) {
setResponse(response, ErrorCode.WRONG_TYPE_TOKEN);
}
else if(exception.equals(ErrorCode.WRONG_TYPE_SIGNATURE.getCode())) {
setResponse(response, ErrorCode.WRONG_TYPE_SIGNATURE);
}
//토큰 만료된 경우
else if(exception.equals(ErrorCode.EXPIRED_TOKEN.getCode())) {
setResponse(response, ErrorCode.EXPIRED_TOKEN);
}
else {
setResponse(response, ErrorCode.ACCESS_DENIED);
setResponse(response, ErrorCode.TOKEN_NOT_EXIST);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.mpnp.baechelin.oauth.exception;
package com.mpnp.baechelin.login.jwt.exception;

public class TokenValidFailedException extends RuntimeException {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.mpnp.baechelin.login.jwt.filter;

import com.mpnp.baechelin.exception.ErrorCode;
import com.mpnp.baechelin.login.jwt.AuthToken;
import com.mpnp.baechelin.login.jwt.AuthTokenProvider;
import com.mpnp.baechelin.util.HeaderUtil;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.security.SignatureException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/* 토큰을 파싱하여 유저 정보를 가지고 오고, 토큰이 유효할 경우 그 유저에게 권한을 부여하는 클래스
* usernamepasswordAuthenticationFilter 보다 먼저 토큰을 바탕으로 유저를 등록시키는 클래스
* OncePerRequestFilter는 요청 당 한번 만 일어나도록 하는 추상클래스이다.
*/
@Slf4j
@RequiredArgsConstructor
public class TokenAuthenticationFilter extends OncePerRequestFilter {

private final AuthTokenProvider tokenProvider;

@Override
protected void doFilterInternal(
HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {

// 요청값의 header에서 토큰을 뽑아온다.
String tokenStr = HeaderUtil.getAccessToken(request);
// String으로 된 token을 AuthToken객체로 변환해준다.
AuthToken token = tokenProvider.convertAuthToken(tokenStr);

try {
if (token != null && token.tokenValidate()) {
Authentication authentication = tokenProvider.getAuthentication(token);
// SecurityContextHolder 에 인증 객체를 넣는다.
SecurityContextHolder.getContext().setAuthentication(authentication);
}
// 에러가 발생했을 때, request에 attribute를 세팅하고 RestAuthenticationEntryPoint로 request를 넘겨준다.
} catch (SignatureException e) {
log.info("잘못된 JWT 서명입니다.");
request.setAttribute("exception", ErrorCode.WRONG_TYPE_SIGNATURE.getCode());
} catch (MalformedJwtException e) {
log.info("유효하지 않은 구성의 JWT 토큰입니다.");
request.setAttribute("exception", ErrorCode.WRONG_TYPE_TOKEN.getCode());
} catch (ExpiredJwtException e) {
log.info("만료된 JWT 토큰입니다.");
request.setAttribute("exception", ErrorCode.EXPIRED_TOKEN.getCode());
} catch (UnsupportedJwtException e) {
log.info("지원되지 않는 형식이나 구성의 JWT 토큰입니다.");
request.setAttribute("exception", ErrorCode.WRONG_TYPE_TOKEN.getCode());
} catch (IllegalArgumentException e) {
log.info(e.toString().split(":")[1].trim());
request.setAttribute("exception", ErrorCode.TOKEN_NOT_EXIST.getCode());
}

filterChain.doFilter(request, response);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.mpnp.baechelin.oauth.handler;
package com.mpnp.baechelin.login.jwt.handler;

import lombok.RequiredArgsConstructor;
import org.springframework.security.access.AccessDeniedException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.mpnp.baechelin.user.repository;
package com.mpnp.baechelin.login.jwt.repository;

import com.mpnp.baechelin.user.domain.UserRefreshToken;
import com.mpnp.baechelin.login.jwt.entity.UserRefreshToken;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.mpnp.baechelin.oauth.service;
package com.mpnp.baechelin.login.jwt.service;

import com.mpnp.baechelin.config.properties.AppProperties;
import com.mpnp.baechelin.oauth.common.AuthResponse;
import com.mpnp.baechelin.oauth.entity.RoleType;
import com.mpnp.baechelin.oauth.token.AuthToken;
import com.mpnp.baechelin.oauth.token.AuthTokenProvider;
import com.mpnp.baechelin.user.domain.UserRefreshToken;
import com.mpnp.baechelin.user.repository.UserRefreshTokenRepository;
import com.mpnp.baechelin.login.oauth.common.AuthResponse;
import com.mpnp.baechelin.login.oauth.entity.RoleType;
import com.mpnp.baechelin.login.jwt.AuthToken;
import com.mpnp.baechelin.login.jwt.AuthTokenProvider;
import com.mpnp.baechelin.login.jwt.entity.UserRefreshToken;
import com.mpnp.baechelin.login.jwt.repository.UserRefreshTokenRepository;
import com.mpnp.baechelin.util.CookieUtil;
import com.mpnp.baechelin.util.HeaderUtil;
import io.jsonwebtoken.Claims;
Expand All @@ -24,7 +24,7 @@
@Service
@RequiredArgsConstructor
@Transactional
public class AuthService {
public class TokenService {

private final AppProperties appProperties;
private final AuthTokenProvider tokenProvider;
Expand Down Expand Up @@ -55,7 +55,7 @@ public AuthResponse refreshToken(HttpServletRequest request, HttpServletResponse
.orElse((null));
AuthToken authRefreshToken = tokenProvider.convertAuthToken(refreshToken);

if (!authRefreshToken.validate()) {
if (!authRefreshToken.tokenValidate()) {
return AuthResponse.invalidRefreshToken();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.mpnp.baechelin.oauth.common;
package com.mpnp.baechelin.login.oauth.common;

import com.mpnp.baechelin.oauth.exception.ErrorCode;
import com.mpnp.baechelin.exception.ErrorCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

Expand All @@ -23,6 +23,7 @@ public static <T> AuthResponse<T> success(String name, T body) {
ErrorCode.SUCCESS_MESSAGE.getMessage()), map);
}

// 이 밑에 코드는 전부 exception 으로 빼기
public static <T> AuthResponse<T> fail() {
return new AuthResponse<>(new AuthResponseHeader(
ErrorCode.FAILED_MESSAGE.getCode(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.mpnp.baechelin.oauth.common;
package com.mpnp.baechelin.login.oauth.common;

import com.mpnp.baechelin.oauth.exception.ErrorCode;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
Expand All @@ -9,6 +8,6 @@
@Setter
@AllArgsConstructor
public class AuthResponseHeader {
private int code;
private String code;
private String message;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.mpnp.baechelin.oauth.entity;
package com.mpnp.baechelin.login.oauth.entity;

import lombok.Getter;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.mpnp.baechelin.oauth.entity;
package com.mpnp.baechelin.login.oauth.entity;

import lombok.AllArgsConstructor;
import lombok.Getter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.mpnp.baechelin.oauth.entity;
package com.mpnp.baechelin.login.oauth.entity;

import com.mpnp.baechelin.user.domain.User;
import lombok.*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.mpnp.baechelin.oauth.exception;
package com.mpnp.baechelin.login.oauth.exception;

public class OAuthProviderMissMatchException extends RuntimeException {

Expand Down
Loading

0 comments on commit a559346

Please sign in to comment.