Skip to content
This repository has been archived by the owner on Oct 22, 2020. It is now read-only.

Commit

Permalink
[#171] feat: auth 관련 controller 를 구현한다.
Browse files Browse the repository at this point in the history
  • Loading branch information
TheDevLuffy committed Jun 26, 2020
1 parent 3369bfc commit ba7fb7b
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 0 deletions.
2 changes: 2 additions & 0 deletions tecobrary-core-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ bootJar {
dependencies {
implementation project(':tecobrary-domain')
implementation project(':tecobrary-external-service')

implementation 'io.jsonwebtoken:jjwt:0.9.1'
}

task copyEnv(type: Copy) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.woowacourse.tecobrary.web.oauth;

import com.woowacourse.tecobrary.common.dto.CoreApiResponse;
import com.woowacourse.tecobrary.web.github.api.GithubApiService;
import com.woowacourse.tecobrary.web.github.dto.GithubApiResponseDto;
import com.woowacourse.tecobrary.web.github.dto.UserJwtInfoDto;
import com.woowacourse.tecobrary.web.github.utils.GithubUserApiUrlBuilder;
import com.woowacourse.tecobrary.web.oauth.jwt.JwtGenerator;
import com.woowacourse.tecobrary.web.oauth.service.GithubUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.view.RedirectView;

@Controller
@Slf4j
@CrossOrigin(origins = "*")
@RequiredArgsConstructor
public class GithubOAuthController {

private final GithubUserApiUrlBuilder githubUserApiUrlBuilder;
private final GithubApiService githubApiService;
private final GithubUserService githubUserService;
private final JwtGenerator jwtGenerator;

@GetMapping("/login/github/oauth2")
public RedirectView github() {
return new RedirectView(githubUserApiUrlBuilder.oauth());
}

@GetMapping("/login/tecobrary")
public CoreApiResponse<GithubApiResponseDto> userAuth(@RequestParam String code) {
String accessToken = githubApiService.getGithubAccessToken(code);
UserJwtInfoDto userJwtInfoDto = githubUserService.getUserByGithubInfo(accessToken);
return CoreApiResponse.success(GithubApiResponseDto.builder()
.user(userJwtInfoDto)
.token(jwtGenerator.generateToken(userJwtInfoDto))
.build());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.woowacourse.tecobrary.web.oauth.jwt;

import com.woowacourse.tecobrary.web.github.dto.UserJwtInfoDto;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;

@Component
public class JwtGenerator {

private static final long JWT_TOKEN_VALIDITY = 60 * 60 * 24 * 7; // one week

private final String secret;

public JwtGenerator(@Value("jwt.secret") String secret) {
this.secret = secret;
}

public String generateToken(UserJwtInfoDto userJwtInfoVo) {
Map<String, Object> claims = new LinkedHashMap<>();
claims.put("id", userJwtInfoVo.getId());
claims.put("email", userJwtInfoVo.getEmail());
claims.put("name", userJwtInfoVo.getName());
claims.put("authorization", userJwtInfoVo.getAuthorization());
claims.put("avatarUrl", userJwtInfoVo.getAvatarUrl());

Map<String, Object> headers = new LinkedHashMap<>();
headers.put("alg", "HS256");
headers.put("typ", "JWT");
return doGenerateToken(claims, headers);
}

public Boolean validateToken(String token, UserJwtInfoDto userJwtInfoVo) {
String userNo = getUserIdFromToken(token);
return (userNo.equals(userJwtInfoVo.getId()) && !isTokenExpired(token));
}

public Boolean isTokenExpired(String token) {
try {
Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
} catch (ExpiredJwtException e) {
return true;
}
}

public String getUserIdFromToken(String token) {
return (String) getClaimFromToken(token, claims -> claims.get("id"));
}

private String doGenerateToken(Map<String, Object> claims, Map<String, Object> headers) {
return Jwts.builder()
.signWith(SignatureAlgorithm.HS256, secret)
.setHeader(headers)
.setClaims(claims)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000))
.compact();
}

private Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}

private <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}

private Claims getAllClaimsFromToken(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.woowacourse.tecobrary.web.oauth.service;

import com.woowacourse.tecobrary.domain.user.entity.User;
import com.woowacourse.tecobrary.domain.user.repository.UserRepository;
import com.woowacourse.tecobrary.web.github.api.GithubApiService;
import com.woowacourse.tecobrary.web.github.dto.GithubUserInfoDto;
import com.woowacourse.tecobrary.web.github.dto.UserJwtInfoDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class GithubUserService {

private final UserRepository userRepository;
private final GithubApiService githubApiService;

public UserJwtInfoDto getUserByGithubInfo(String githubAccessToken) {
GithubUserInfoDto githubUserInfoDto = githubApiService.getGithubUserInfo(githubAccessToken);

User user = userRepository.findByGithubId(githubUserInfoDto.getId())
.orElse(newGithubUser(githubAccessToken, githubUserInfoDto));

return UserJwtInfoDto.builder()
.id(user.getId())
.name(user.getName())
.email(user.getEmail())
.avatarUrl(user.getAvatarUrl())
.authorization(user.getAuthorization())
.build();
}

private User newGithubUser(String githubAccessToken, GithubUserInfoDto githubUser) {
String email = githubApiService.getGithubUserEmail(githubAccessToken);
User user = User.builder()
.githubId(githubUser.getId())
.email(email)
.avatarUrl(githubUser.getAvatar_url())
.name(githubUser.getName())
.authorization("NONE")
.build();
return userRepository.save(user);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.Optional;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

Optional<User> findByGithubId(String githubId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

package com.woowacourse.tecobrary.web.github.dto;

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
Expand All @@ -23,6 +24,7 @@ public class GithubApiResponseDto {
private UserJwtInfoDto user;
private String token;

@Builder
public GithubApiResponseDto(UserJwtInfoDto user, String token) {
this.user = user;
this.token = token;
Expand Down

0 comments on commit ba7fb7b

Please sign in to comment.