From 7a3f84cd867ae1f1770d68d252969b0350466fb8 Mon Sep 17 00:00:00 2001 From: hiro Date: Thu, 17 Jun 2021 16:25:34 +0900 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20login.html=20=EC=9E=91=EC=84=B1=20?= =?UTF-8?q?=EC=9D=B4=ED=9B=84=20front=20=EC=84=9C=EB=B2=84=EB=A1=9C=20?= =?UTF-8?q?=EB=8C=80=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/static/login.html | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 be/issue-tracker-be/src/main/resources/static/login.html diff --git a/be/issue-tracker-be/src/main/resources/static/login.html b/be/issue-tracker-be/src/main/resources/static/login.html new file mode 100644 index 000000000..d7a18f56f --- /dev/null +++ b/be/issue-tracker-be/src/main/resources/static/login.html @@ -0,0 +1,10 @@ + + + + + login + + + login + + From 64996f778e64b51d80af22dce38bddf0c8af67ed Mon Sep 17 00:00:00 2001 From: hiro Date: Thu, 17 Jun 2021 16:26:11 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20auth=EA=B4=80=EB=A0=A8=20properties?= =?UTF-8?q?=20.gitignore=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- be/issue-tracker-be/.gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/be/issue-tracker-be/.gitignore b/be/issue-tracker-be/.gitignore index c2065bc26..515a8fe9e 100644 --- a/be/issue-tracker-be/.gitignore +++ b/be/issue-tracker-be/.gitignore @@ -35,3 +35,6 @@ out/ ### VS Code ### .vscode/ + +### auth +auth.properties From 9133730f818963893cad3cb7a9a6ce954b39e118 Mon Sep 17 00:00:00 2001 From: hiro Date: Thu, 17 Jun 2021 16:27:26 +0900 Subject: [PATCH 3/9] =?UTF-8?q?feat:=20GitHub=EC=9D=84=20=ED=86=B5?= =?UTF-8?q?=ED=95=9C=20OAuth=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/config/InterceptorConfig.java | 13 ++++ .../auth/controller/AuthController.java | 49 +++++++++++++++ .../issuetracker/auth/dto/AuthRequest.java | 13 ++++ .../issuetracker/auth/dto/AuthResponse.java | 13 ++++ .../auth/dto/GitHubAccessTokenRequest.java | 33 ++++++++++ .../auth/dto/GitHubAccessTokenResponse.java | 56 +++++++++++++++++ .../issuetracker/auth/dto/GitHubOAuth.java | 16 +++++ .../auth/service/AuthService.java | 61 +++++++++++++++++++ .../codesquad/issuetracker/user/UserDto.java | 36 +++++++++++ 9 files changed, 290 insertions(+) create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/config/InterceptorConfig.java create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/controller/AuthController.java create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/AuthRequest.java create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/AuthResponse.java create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/GitHubAccessTokenRequest.java create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/GitHubAccessTokenResponse.java create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/GitHubOAuth.java create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/service/AuthService.java create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/user/UserDto.java diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/config/InterceptorConfig.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/config/InterceptorConfig.java new file mode 100644 index 000000000..9afc2f7c8 --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/config/InterceptorConfig.java @@ -0,0 +1,13 @@ +package com.codesquad.issuetracker.auth.config; + +import com.codesquad.issuetracker.auth.intercepter.LoginInterceptor; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +public class InterceptorConfig implements WebMvcConfigurer { + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new LoginInterceptor()) + .addPathPatterns("/auth/**"); + } +} diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/controller/AuthController.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/controller/AuthController.java new file mode 100644 index 000000000..4e6b2050a --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/controller/AuthController.java @@ -0,0 +1,49 @@ +package com.codesquad.issuetracker.auth.controller; + +import com.codesquad.issuetracker.auth.dto.AuthResponse; +import com.codesquad.issuetracker.auth.service.AuthService; +import com.codesquad.issuetracker.auth.dto.GitHubAccessTokenResponse; +import com.codesquad.issuetracker.auth.util.JwtUtil; +import com.codesquad.issuetracker.user.UserDto; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import javax.security.auth.message.AuthException; + +@RequestMapping("/auth") +@Controller +public class AuthController { + + private final AuthService authService; + + public AuthController(AuthService authService) { + this.authService = authService; + } + + //Fixme : front로 변경 + @GetMapping("/callback") + public void callback(@RequestParam(value = "code") String code) throws AuthException { + auth(code); + } + + @GetMapping() + public ResponseEntity auth(String code) throws AuthException { + GitHubAccessTokenResponse token = authService.getAccessToken(code); + String accessToken = token.getAccessToken(); + + UserDto userDto = authService.getUserFromGitHub(accessToken); + + AuthResponse authResponse = new AuthResponse(JwtUtil.createJwt(userDto)); + + ResponseEntity authResponseResponseEntity = ResponseEntity.status(HttpStatus.CREATED). + body(new AuthResponse(JwtUtil.createJwt(userDto))); + + return authResponseResponseEntity; + } + + +} diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/AuthRequest.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/AuthRequest.java new file mode 100644 index 000000000..8c755ef78 --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/AuthRequest.java @@ -0,0 +1,13 @@ +package com.codesquad.issuetracker.auth.dto; + +public class AuthRequest { + private String code; + + public AuthRequest(String code) { + this.code = code; + } + + public String getCode() { + return code; + } +} diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/AuthResponse.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/AuthResponse.java new file mode 100644 index 000000000..a58f2b4ca --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/AuthResponse.java @@ -0,0 +1,13 @@ +package com.codesquad.issuetracker.auth.dto; + +public class AuthResponse { + private final String token; + + public AuthResponse(String token) { + this.token = token; + } + + public String getToken() { + return token; + } +} diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/GitHubAccessTokenRequest.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/GitHubAccessTokenRequest.java new file mode 100644 index 000000000..c5052d7bd --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/GitHubAccessTokenRequest.java @@ -0,0 +1,33 @@ +package com.codesquad.issuetracker.auth.dto; + +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class GitHubAccessTokenRequest { + @JsonProperty("client_id") + private final String clientId; + + @JsonProperty("client_secret") + private final String clientSecret; + + @JsonProperty("code") + private final String code; + + public GitHubAccessTokenRequest(String clientId, String clientSecret, String code) { + this.clientId = clientId; + this.clientSecret = clientSecret; + this.code = code; + } + + public String getClientId() { + return clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public String getCode() { + return code; + } +} diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/GitHubAccessTokenResponse.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/GitHubAccessTokenResponse.java new file mode 100644 index 000000000..c73952105 --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/GitHubAccessTokenResponse.java @@ -0,0 +1,56 @@ +package com.codesquad.issuetracker.auth.dto; + +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; + +public class GitHubAccessTokenResponse { + @JsonProperty("access_token") + private String accessToken; + + @JsonProperty("token_type") + private String tokenType; + + @JsonProperty("scope") + private String scope; + + public GitHubAccessTokenResponse() { + } + + public GitHubAccessTokenResponse(String accessToken, String tokenType, String scope) { + this.accessToken = accessToken; + this.tokenType = tokenType; + this.scope = scope; + } + + public String getScope() { + return scope; + } + + public String getTokenType() { + return tokenType; + } + + public String getAccessToken() { + return accessToken; + } + + @JsonSetter("access_token") + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + + @JsonSetter("token_type") + public void setTokenType(String tokenType) { + this.tokenType = tokenType; + } + + + + @JsonSetter("scope") + public void setScope(String scope) { + this.scope = scope; + } + +} diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/GitHubOAuth.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/GitHubOAuth.java new file mode 100644 index 000000000..b8d074118 --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/GitHubOAuth.java @@ -0,0 +1,16 @@ +package com.codesquad.issuetracker.auth.dto; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; + +@PropertySource(value = "classpath:auth.properties") +public class GitHubOAuth { + + @Value("${client_id}") + private static String clientId; + + @Value("${client_secret}") + private static String clientSecret; + + private static String code; +} diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/service/AuthService.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/service/AuthService.java new file mode 100644 index 000000000..33f47a4af --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/service/AuthService.java @@ -0,0 +1,61 @@ +package com.codesquad.issuetracker.auth.service; + +import com.codesquad.issuetracker.auth.dto.GitHubAccessTokenRequest; +import com.codesquad.issuetracker.auth.dto.GitHubAccessTokenResponse; +import com.codesquad.issuetracker.user.UserDto; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.PropertySource; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.*; + +import javax.security.auth.message.AuthException; +import java.util.Optional; + +@PropertySource(value = "classpath:auth.properties") +@Service +public class AuthService { + @Value("${gitHub_AccessTokenUri}") + private String gitHubAccessTokenUri; + + @Value("${gitHub_UserUri}") + private String gitHubUserUri; + + @Value("${client_id}") + private String clientId; + + @Value("${client_secret}") + private String clientSecret; + + private static RestTemplate restTemplate = new RestTemplate(); + + public GitHubAccessTokenResponse getAccessToken(String code) throws AuthException { + RequestEntity request = RequestEntity + .post(gitHubAccessTokenUri) + .header("Accept", "application/json") + .body(new GitHubAccessTokenRequest(clientId, clientSecret, code)); + + ResponseEntity response = restTemplate + .exchange(request, GitHubAccessTokenResponse.class); + + return Optional.ofNullable(response.getBody()) + .orElseThrow(() -> new AuthException("Access Token 획득 실패")); + } + + public UserDto getUserFromGitHub(String accessToken) throws AuthException { + RequestEntity request = RequestEntity + .get(gitHubUserUri) + .header("Accept", "application/json") + .header("Authorization", "token " + accessToken) + .build(); + + ResponseEntity response = restTemplate + .exchange(request, UserDto.class); + + return Optional.ofNullable(response.getBody()) + .orElseThrow(() -> new AuthException("유저 정보 획득 실패")); + } + + +} diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/user/UserDto.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/user/UserDto.java new file mode 100644 index 000000000..4c0bd1706 --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/user/UserDto.java @@ -0,0 +1,36 @@ +package com.codesquad.issuetracker.user; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class UserDto { + @JsonProperty("login") + private String login; + + @JsonProperty("avatar_url") + private String avatarUrl; + + @JsonProperty("name") + private String name; + + public UserDto() { + } + + public UserDto(String login, String avatarUrl, String name) { + this.login = login; + this.avatarUrl = avatarUrl; + this.name = name; + } + + public String getLogin() { + return login; + } + + public String getAvatarUrl() { + return avatarUrl; + } + + public String getName() { + return name; + } + +} From af67076f8b77709f98c6e859187eba955ff68f22 Mon Sep 17 00:00:00 2001 From: hiro Date: Thu, 17 Jun 2021 16:28:58 +0900 Subject: [PATCH 4/9] =?UTF-8?q?feat:=20jwt=EA=B4=80=EB=A0=A8=20util?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=9E=91=EC=84=B1.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issuetracker/auth/util/JwtUtil.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/util/JwtUtil.java diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/util/JwtUtil.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/util/JwtUtil.java new file mode 100644 index 000000000..02e450fee --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/util/JwtUtil.java @@ -0,0 +1,53 @@ +package com.codesquad.issuetracker.auth.util; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTVerificationException; +import com.auth0.jwt.interfaces.DecodedJWT; +import com.auth0.jwt.interfaces.JWTVerifier; +import com.codesquad.issuetracker.auth.exception.JWTCreationException; +import com.codesquad.issuetracker.auth.exception.JwtException; +import com.codesquad.issuetracker.user.UserDto; +import lombok.Data; + +@Data +public class JwtUtil { + private static final String JWT_SECRET = "jwtSecret"; + private static final String JWT_ISSUER = "jwtIssuer"; + private static final String USER_LOGIN = "login"; + private static final String USER_NAME = "name"; + private static final String USER_AVATAR = "avatar"; + private static final Algorithm algorithmHS = Algorithm.HMAC256(JWT_SECRET); + + public static String createJwt(UserDto user) { + try { + return JWT.create() + .withIssuer(JWT_ISSUER) + .withClaim(USER_LOGIN, user.getLogin()) + .withClaim(USER_NAME, user.getName()) + .withClaim(USER_AVATAR, user.getAvatarUrl()) + .sign(algorithmHS); + } catch (JWTCreationException exception) { + throw new JwtException("JWT 생성 실패"); + } + } + + public static UserDto decodeJwt(String token) throws JwtException { + try { + JWTVerifier verifier = JWT.require(algorithmHS) + .withIssuer(JWT_ISSUER) + .build(); + + DecodedJWT jwt = verifier.verify(token); + + String login = jwt.getClaim(USER_LOGIN).asString(); + String name = jwt.getClaim(USER_NAME).asString(); + String avatarUri = jwt.getClaim(USER_AVATAR).asString(); + + return new UserDto(login, name, avatarUri); + } catch (JWTVerificationException exception) { + throw new JwtException("잘못된 jwt 입니다."); + } + } + +} From e607d58cdd4ad9de1186bbe9dfa477ac95370c68 Mon Sep 17 00:00:00 2001 From: hiro Date: Thu, 17 Jun 2021 16:29:21 +0900 Subject: [PATCH 5/9] =?UTF-8?q?feat:=20Auth=EA=B4=80=EB=A0=A8=20Exception?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/exception/AuthenticationException.java | 7 +++++++ .../issuetracker/auth/exception/JWTCreationException.java | 7 +++++++ .../issuetracker/auth/exception/JwtException.java | 7 +++++++ 3 files changed, 21 insertions(+) create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/AuthenticationException.java create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/JWTCreationException.java create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/JwtException.java diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/AuthenticationException.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/AuthenticationException.java new file mode 100644 index 000000000..83f4c47dc --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/AuthenticationException.java @@ -0,0 +1,7 @@ +package com.codesquad.issuetracker.auth.exception; + +public class AuthenticationException extends RuntimeException{ + public AuthenticationException(String message) { + super(message); + } +} diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/JWTCreationException.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/JWTCreationException.java new file mode 100644 index 000000000..a8e9c9e01 --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/JWTCreationException.java @@ -0,0 +1,7 @@ +package com.codesquad.issuetracker.auth.exception; + +public class JWTCreationException extends RuntimeException{ + public JWTCreationException(String message) { + super(message); + } +} diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/JwtException.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/JwtException.java new file mode 100644 index 000000000..40207926b --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/JwtException.java @@ -0,0 +1,7 @@ +package com.codesquad.issuetracker.auth.exception; + +public class JwtException extends RuntimeException { + public JwtException(String message) { + super(message); + } +} From 5ba2f6f31db93fd8d859e6d583112844862e5347 Mon Sep 17 00:00:00 2001 From: hiro Date: Thu, 17 Jun 2021 16:29:52 +0900 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=EC=8B=9C=20=ED=95=84=EC=9A=94=ED=95=9C=20=EC=95=A0=EB=85=B8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EC=85=98=EA=B3=BC,=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=EC=85=89=ED=84=B0=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../issuetracker/auth/LoginRequired.java | 16 ++++++++ .../auth/intercepter/LoginInterceptor.java | 38 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/LoginRequired.java create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/intercepter/LoginInterceptor.java diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/LoginRequired.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/LoginRequired.java new file mode 100644 index 000000000..a5a283a43 --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/LoginRequired.java @@ -0,0 +1,16 @@ +package com.codesquad.issuetracker.auth; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +// NOTE: Login이 필요한 API일 경우 사용 +@Target({METHOD, ANNOTATION_TYPE}) +@Retention(RUNTIME) +@Documented +public @interface LoginRequired { +} diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/intercepter/LoginInterceptor.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/intercepter/LoginInterceptor.java new file mode 100644 index 000000000..619023713 --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/intercepter/LoginInterceptor.java @@ -0,0 +1,38 @@ +package com.codesquad.issuetracker.auth.intercepter; + +import com.codesquad.issuetracker.auth.LoginRequired; +import com.codesquad.issuetracker.auth.exception.AuthenticationException; +import com.codesquad.issuetracker.auth.util.JwtUtil; +import com.codesquad.issuetracker.user.UserDto; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import static org.springframework.http.HttpHeaders.AUTHORIZATION; + +public class LoginInterceptor implements HandlerInterceptor { + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + if (isLoginRequired(handler)) { + authenticate(request); + } + return true; + } + + private boolean isLoginRequired(Object handler) { + return handler instanceof HandlerMethod + && ((HandlerMethod) handler).hasMethodAnnotation(LoginRequired.class); + } + + private void authenticate(HttpServletRequest request) { + String[] splitAuth = request.getHeader(AUTHORIZATION).split(" "); + String tokenType = splitAuth[0].toLowerCase(); + if (splitAuth.length < 1 || !tokenType.equals("bearer")) { + throw new AuthenticationException("잘못된 Authorization Header 입니다."); + } + UserDto userDto = JwtUtil.decodeJwt(splitAuth[1]); + request.setAttribute("user", userDto); + } +} From fbc5e78d87347f0459a30aa37b8bf82ecae41734 Mon Sep 17 00:00:00 2001 From: hiro Date: Thu, 17 Jun 2021 16:31:07 +0900 Subject: [PATCH 7/9] =?UTF-8?q?add:=20jwt=EA=B4=80=EB=A0=A8=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- be/issue-tracker-be/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/be/issue-tracker-be/build.gradle b/be/issue-tracker-be/build.gradle index 7551cba17..2a9286dd5 100644 --- a/be/issue-tracker-be/build.gradle +++ b/be/issue-tracker-be/build.gradle @@ -24,12 +24,15 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-hateoas' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' +ㄹ implementation 'org.projectlombok:lombok:1.18.16' testImplementation 'org.springframework.boot:spring-boot-starter-test' annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' annotationProcessor 'org.projectlombok:lombok' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' runtimeOnly 'mysql:mysql-connector-java' + implementation 'com.auth0:java-jwt:3.8.3' + implementation 'org.springdoc:springdoc-openapi-ui:1.5.8' implementation 'org.springdoc:springdoc-openapi-data-rest:1.5.8' From 90998f36431cf38d2245bd27da0b6563634732f1 Mon Sep 17 00:00:00 2001 From: hiro Date: Fri, 18 Jun 2021 11:04:51 +0900 Subject: [PATCH 8/9] =?UTF-8?q?fix:=20gradle=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- be/issue-tracker-be/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/be/issue-tracker-be/build.gradle b/be/issue-tracker-be/build.gradle index 2a9286dd5..769bc9644 100644 --- a/be/issue-tracker-be/build.gradle +++ b/be/issue-tracker-be/build.gradle @@ -24,7 +24,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-hateoas' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' -ㄹ implementation 'org.projectlombok:lombok:1.18.16' + implementation 'org.projectlombok:lombok:1.18.16' testImplementation 'org.springframework.boot:spring-boot-starter-test' annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' annotationProcessor 'org.projectlombok:lombok' From 7d135a94b9ec49bfcd49e8acd2650a1032a414a4 Mon Sep 17 00:00:00 2001 From: hiro Date: Fri, 25 Jun 2021 02:37:45 +0900 Subject: [PATCH 9/9] =?UTF-8?q?feat:=20Client=20Type=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FE, IOS타입에 따라서 clientId, secret의 값을 다르게 리턴 --- .../auth/controller/AuthController.java | 13 ++++--- .../codesquad/issuetracker/auth/dto/Type.java | 20 +++++++++++ .../auth/{ => exception}/LoginRequired.java | 2 +- .../auth/intercepter/LoginInterceptor.java | 2 +- .../auth/service/AuthService.java | 35 +++++++++++++++++-- 5 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/Type.java rename be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/{ => exception}/LoginRequired.java (89%) diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/controller/AuthController.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/controller/AuthController.java index 4e6b2050a..49faa1626 100644 --- a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/controller/AuthController.java +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/controller/AuthController.java @@ -1,6 +1,7 @@ package com.codesquad.issuetracker.auth.controller; import com.codesquad.issuetracker.auth.dto.AuthResponse; +import com.codesquad.issuetracker.auth.dto.Type; import com.codesquad.issuetracker.auth.service.AuthService; import com.codesquad.issuetracker.auth.dto.GitHubAccessTokenResponse; import com.codesquad.issuetracker.auth.util.JwtUtil; @@ -26,18 +27,16 @@ public AuthController(AuthService authService) { //Fixme : front로 변경 @GetMapping("/callback") - public void callback(@RequestParam(value = "code") String code) throws AuthException { - auth(code); + public ResponseEntity callback(@RequestParam(value = "code") String code) throws AuthException { + return auth(code, "fe"); } - @GetMapping() - public ResponseEntity auth(String code) throws AuthException { - GitHubAccessTokenResponse token = authService.getAccessToken(code); + @GetMapping + public ResponseEntity auth(String code, String type) throws AuthException { + GitHubAccessTokenResponse token = authService.getAccessToken(code, type); String accessToken = token.getAccessToken(); UserDto userDto = authService.getUserFromGitHub(accessToken); - - AuthResponse authResponse = new AuthResponse(JwtUtil.createJwt(userDto)); ResponseEntity authResponseResponseEntity = ResponseEntity.status(HttpStatus.CREATED). body(new AuthResponse(JwtUtil.createJwt(userDto))); diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/Type.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/Type.java new file mode 100644 index 000000000..65a58390d --- /dev/null +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/dto/Type.java @@ -0,0 +1,20 @@ +package com.codesquad.issuetracker.auth.dto; + +public enum Type { + IOS("ios"), + FE("fe"); + + private final String type; + + Type(String type) { + this.type = type; + } + + public static boolean isFe(String type) { + return FE.type.equals(type); + } + + public static boolean isIos(String type) { + return IOS.type.equals(type); + } +} diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/LoginRequired.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/LoginRequired.java similarity index 89% rename from be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/LoginRequired.java rename to be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/LoginRequired.java index a5a283a43..bc8908f94 100644 --- a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/LoginRequired.java +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/exception/LoginRequired.java @@ -1,4 +1,4 @@ -package com.codesquad.issuetracker.auth; +package com.codesquad.issuetracker.auth.exception; import java.lang.annotation.Documented; import java.lang.annotation.Retention; diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/intercepter/LoginInterceptor.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/intercepter/LoginInterceptor.java index 619023713..1774fdeb0 100644 --- a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/intercepter/LoginInterceptor.java +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/intercepter/LoginInterceptor.java @@ -1,6 +1,6 @@ package com.codesquad.issuetracker.auth.intercepter; -import com.codesquad.issuetracker.auth.LoginRequired; +import com.codesquad.issuetracker.auth.exception.LoginRequired; import com.codesquad.issuetracker.auth.exception.AuthenticationException; import com.codesquad.issuetracker.auth.util.JwtUtil; import com.codesquad.issuetracker.user.UserDto; diff --git a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/service/AuthService.java b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/service/AuthService.java index 33f47a4af..25a3a2727 100644 --- a/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/service/AuthService.java +++ b/be/issue-tracker-be/src/main/java/com/codesquad/issuetracker/auth/service/AuthService.java @@ -2,6 +2,7 @@ import com.codesquad.issuetracker.auth.dto.GitHubAccessTokenRequest; import com.codesquad.issuetracker.auth.dto.GitHubAccessTokenResponse; +import com.codesquad.issuetracker.auth.dto.Type; import com.codesquad.issuetracker.user.UserDto; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; @@ -28,13 +29,20 @@ public class AuthService { @Value("${client_secret}") private String clientSecret; + @Value("${ios_client_id}") + private String iosClientId; + + @Value("${ios_client_secret}") + private String iosClientSecret; + private static RestTemplate restTemplate = new RestTemplate(); - public GitHubAccessTokenResponse getAccessToken(String code) throws AuthException { + public GitHubAccessTokenResponse getAccessToken(String code, String type) throws AuthException { + RequestEntity request = RequestEntity .post(gitHubAccessTokenUri) .header("Accept", "application/json") - .body(new GitHubAccessTokenRequest(clientId, clientSecret, code)); + .body(new GitHubAccessTokenRequest(getClientId(type), getClientSecret(type), code)); ResponseEntity response = restTemplate .exchange(request, GitHubAccessTokenResponse.class); @@ -57,5 +65,28 @@ public UserDto getUserFromGitHub(String accessToken) throws AuthException { .orElseThrow(() -> new AuthException("유저 정보 획득 실패")); } + private String getClientId(String type) { + if(Type.isFe(type)) { + return clientId; + } + + if(Type.isIos(type)) { + return iosClientId; + } + + throw new RuntimeException("타입 확인 불가"); + } + + private String getClientSecret(String type) { + if(Type.isFe(type)) { + return clientSecret; + } + + if(Type.isIos(type)) { + return iosClientSecret; + } + + throw new RuntimeException("타입 확인 불가"); + } }