-
Notifications
You must be signed in to change notification settings - Fork 2
Be/oauth/main #121
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
base: be/main
Are you sure you want to change the base?
Be/oauth/main #121
Changes from all commits
7a3f84c
64996f7
9133730
af67076
e607d58
5ba2f6f
fbc5e78
90998f3
7d135a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,3 +35,6 @@ out/ | |
|
|
||
| ### VS Code ### | ||
| .vscode/ | ||
|
|
||
| ### auth | ||
| auth.properties | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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' | ||
|
Comment on lines
30
to
31
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기에 의존성 등록 돼 있습니다~ |
||
| 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' | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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/**"); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| 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; | ||
| 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 ResponseEntity<AuthResponse> callback(@RequestParam(value = "code") String code) throws AuthException { | ||
| return auth(code, "fe"); | ||
| } | ||
|
|
||
| @GetMapping | ||
| public ResponseEntity<AuthResponse> auth(String code, String type) throws AuthException { | ||
| GitHubAccessTokenResponse token = authService.getAccessToken(code, type); | ||
| String accessToken = token.getAccessToken(); | ||
|
|
||
| UserDto userDto = authService.getUserFromGitHub(accessToken); | ||
|
|
||
| ResponseEntity<AuthResponse> authResponseResponseEntity = ResponseEntity.status(HttpStatus.CREATED). | ||
| body(new AuthResponse(JwtUtil.createJwt(userDto))); | ||
|
|
||
| return authResponseResponseEntity; | ||
| } | ||
|
|
||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } | ||
| } | ||
|
Comment on lines
+3
to
+13
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이런 부분은 롬복으로 처리해도 충분하다고 봅니다 |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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") | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. JsonProperty 있으면 필요없지 않나요? |
||
| 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; | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package com.codesquad.issuetracker.auth.exception; | ||
|
|
||
| public class AuthenticationException extends RuntimeException{ | ||
| public AuthenticationException(String message) { | ||
| super(message); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package com.codesquad.issuetracker.auth.exception; | ||
|
|
||
| public class JWTCreationException extends RuntimeException{ | ||
| public JWTCreationException(String message) { | ||
| super(message); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package com.codesquad.issuetracker.auth.exception; | ||
|
|
||
| public class JwtException extends RuntimeException { | ||
| public JwtException(String message) { | ||
| super(message); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package com.codesquad.issuetracker.auth.exception; | ||
|
|
||
| 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 { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package com.codesquad.issuetracker.auth.intercepter; | ||
|
|
||
| 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; | ||
| 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 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 수정사항은 아니고 잘 몰라서 질문인데, instanceof는 안티 패턴이라고 알고 있어요. 핸들러 메소드가 아니면 예외 발생해야 하는거 아닌가요? 혹시 써야 하는 이유가 뭔가요? |
||
| && ((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]); | ||
|
Comment on lines
+30
to
+35
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 유틸성 말고 객체로 처리할 수도 있겠네요 |
||
| request.setAttribute("user", userDto); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
없애주세요