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

cucumber 실습 PR #421

Open
wants to merge 4 commits into
base: junwoochoi2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
22 changes: 22 additions & 0 deletions src/main/java/nextstep/auth/AuthConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package nextstep.auth;

import nextstep.auth.principal.AuthenticationPrincipalArgumentResolver;
import nextstep.auth.token.JwtTokenProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class AuthConfig implements WebMvcConfigurer {
private JwtTokenProvider jwtTokenProvider;

public AuthConfig(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}

@Override
public void addArgumentResolvers(List argumentResolvers) {
argumentResolvers.add(new AuthenticationPrincipalArgumentResolver(jwtTokenProvider));
}
}
8 changes: 8 additions & 0 deletions src/main/java/nextstep/auth/AuthenticationException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package nextstep.auth;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(HttpStatus.UNAUTHORIZED)
public class AuthenticationException extends RuntimeException {
}
11 changes: 11 additions & 0 deletions src/main/java/nextstep/auth/principal/AuthenticationPrincipal.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package nextstep.auth.principal;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthenticationPrincipal {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package nextstep.auth.principal;

import nextstep.auth.AuthenticationException;
import nextstep.auth.token.JwtTokenProvider;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

public class AuthenticationPrincipalArgumentResolver implements HandlerMethodArgumentResolver {
private JwtTokenProvider jwtTokenProvider;

public AuthenticationPrincipalArgumentResolver(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
}

@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(AuthenticationPrincipal.class);
}

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
String authorization = webRequest.getHeader("Authorization");
if (!"bearer".equalsIgnoreCase(authorization.split(" ")[0])) {
throw new AuthenticationException();
}
String token = authorization.split(" ")[1];

String username = jwtTokenProvider.getPrincipal(token);

return new UserPrincipal(username);
}
}
13 changes: 13 additions & 0 deletions src/main/java/nextstep/auth/principal/UserPrincipal.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package nextstep.auth.principal;

public class UserPrincipal {
private String username;

public UserPrincipal(String username) {
this.username = username;
}

public String getUsername() {
return username;
}
}
43 changes: 43 additions & 0 deletions src/main/java/nextstep/auth/token/JwtTokenProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package nextstep.auth.token;

import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class JwtTokenProvider {
@Value("${security.jwt.token.secret-key}")
private String secretKey;
@Value("${security.jwt.token.expire-length}")
private long validityInMilliseconds;

public String createToken(String principal) {
Claims claims = Jwts.claims().setSubject(principal);
Date now = new Date();
Date validity = new Date(now.getTime() + validityInMilliseconds);

return Jwts.builder()
.setClaims(claims)
.setIssuedAt(now)
.setExpiration(validity)
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
}

public String getPrincipal(String token) {
return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject();
}

public boolean validateToken(String token) {
try {
Jws<Claims> claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);

return !claims.getBody().getExpiration().before(new Date());
} catch (JwtException | IllegalArgumentException e) {
return false;
}
}
}

30 changes: 30 additions & 0 deletions src/main/java/nextstep/auth/token/TokenController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package nextstep.auth.token;

import nextstep.auth.token.oauth2.github.GithubTokenRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TokenController {
private TokenService tokenService;

public TokenController(TokenService tokenService) {
this.tokenService = tokenService;
}

@PostMapping("/login/token")
public ResponseEntity<TokenResponse> createToken(@RequestBody TokenRequest request) {
TokenResponse response = tokenService.createToken(request.getEmail(), request.getPassword());

return ResponseEntity.ok(response);
}

@PostMapping("/login/github")
public ResponseEntity<TokenResponse> createTokenByGithub(@RequestBody GithubTokenRequest request) {
TokenResponse response = tokenService.createTokenFromGithub(request.getCode());

return ResponseEntity.ok(response);
}
}
22 changes: 22 additions & 0 deletions src/main/java/nextstep/auth/token/TokenRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package nextstep.auth.token;

public class TokenRequest {
private String email;
private String password;

public TokenRequest() {
}

public TokenRequest(String email, String password) {
this.email = email;
this.password = password;
}

public String getEmail() {
return email;
}

public String getPassword() {
return password;
}
}
16 changes: 16 additions & 0 deletions src/main/java/nextstep/auth/token/TokenResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package nextstep.auth.token;

public class TokenResponse {
private String accessToken;

public TokenResponse() {
}

public TokenResponse(String accessToken) {
this.accessToken = accessToken;
}

public String getAccessToken() {
return accessToken;
}
}
52 changes: 52 additions & 0 deletions src/main/java/nextstep/auth/token/TokenService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package nextstep.auth.token;

import nextstep.auth.AuthenticationException;
import nextstep.auth.token.oauth2.OAuth2User;
import nextstep.auth.token.oauth2.OAuth2UserService;
import nextstep.auth.token.oauth2.github.GithubClient;
import nextstep.auth.token.oauth2.github.GithubProfileResponse;
import nextstep.auth.userdetails.UserDetails;
import nextstep.auth.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;

@Service
public class TokenService {
private UserDetailsService userDetailsService;
private OAuth2UserService oAuth2UserService;
private JwtTokenProvider jwtTokenProvider;
private GithubClient githubClient;

public TokenService(
UserDetailsService userDetailsService,
OAuth2UserService oAuth2UserService,
JwtTokenProvider jwtTokenProvider,
GithubClient githubClient
) {
this.userDetailsService = userDetailsService;
this.oAuth2UserService = oAuth2UserService;
this.jwtTokenProvider = jwtTokenProvider;
this.githubClient = githubClient;
}

public TokenResponse createToken(String email, String password) {
UserDetails userDetails = userDetailsService.loadUserByUsername(email);
if (!userDetails.getPassword().equals(password)) {
throw new AuthenticationException();
}

String token = jwtTokenProvider.createToken(userDetails.getUsername());

return new TokenResponse(token);
}

public TokenResponse createTokenFromGithub(String code) {
String accessTokenFromGithub = githubClient.getAccessTokenFromGithub(code);
GithubProfileResponse githubProfile = githubClient.getGithubProfileFromGithub(accessTokenFromGithub);

OAuth2User oAuth2User = oAuth2UserService.loadUser(githubProfile);

String token = jwtTokenProvider.createToken(oAuth2User.getUsername());

return new TokenResponse(token);
}
}
5 changes: 5 additions & 0 deletions src/main/java/nextstep/auth/token/oauth2/OAuth2User.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package nextstep.auth.token.oauth2;

public interface OAuth2User {
String getUsername();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package nextstep.auth.token.oauth2;

public interface OAuth2UserRequest {
String getUsername();

Integer getAge();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package nextstep.auth.token.oauth2;

public interface OAuth2UserService {
OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package nextstep.auth.token.oauth2.github;

public class GithubAccessTokenRequest {

private String code;
private String client_id;
private String client_secret;

public GithubAccessTokenRequest(String code, String client_id, String client_secret) {
this.code = code;
this.client_id = client_id;
this.client_secret = client_secret;
}

public GithubAccessTokenRequest() {
}

public String getCode() {
return code;
}

public String getClient_id() {
return client_id;
}

public String getClient_secret() {
return client_secret;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package nextstep.auth.token.oauth2.github;

import com.fasterxml.jackson.annotation.JsonProperty;

public class GithubAccessTokenResponse {

@JsonProperty("access_token")
private String accessToken;
@JsonProperty("token_type")
private String tokenType;
private String scope;
private String bearer;

public GithubAccessTokenResponse() {

}

public GithubAccessTokenResponse(String accessToken,
String tokenType,
String scope,
String bearer) {
this.accessToken = accessToken;
this.tokenType = tokenType;
this.scope = scope;
this.bearer = bearer;
}

public String getAccessToken() {
return accessToken;
}

public String getTokenType() {
return tokenType;
}

public String getScope() {
return scope;
}

public String getBearer() {
return bearer;
}
}
Loading