Skip to content

Commit

Permalink
feat/GH-89-naver-oauth (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
jinlee1703 authored Jul 15, 2023
2 parents 83115ad + da47445 commit 60b83ad
Show file tree
Hide file tree
Showing 4 changed files with 219 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.swmaestro.repl.gifthub.auth.dto.SignInDto;
import org.swmaestro.repl.gifthub.auth.dto.SignUpDto;
import org.swmaestro.repl.gifthub.auth.dto.TokenDto;
import org.swmaestro.repl.gifthub.auth.service.AuthService;
import org.swmaestro.repl.gifthub.auth.service.MemberService;
import org.swmaestro.repl.gifthub.auth.service.NaverService;
import org.swmaestro.repl.gifthub.auth.service.RefreshTokenService;
import org.swmaestro.repl.gifthub.util.JwtProvider;

import java.io.IOException;

@RestController
@RequestMapping("/auth")
@RequiredArgsConstructor
Expand All @@ -21,6 +26,7 @@ public class AuthController {
private final AuthService authService;
private final RefreshTokenService refreshTokenService;
private final JwtProvider jwtProvider;
private final NaverService naverService;

@PostMapping("/sign-up")
@Operation(summary = "회원가입 메서드", description = "사용자가 회원가입을 하기 위한 메서드입니다.")
Expand Down Expand Up @@ -51,4 +57,19 @@ public TokenDto validateRefreshToken(@RequestHeader("Authorization") String refr
refreshTokenService.storeRefreshToken(tokenDto, jwtProvider.getUsername(refreshToken));
return tokenDto;
}

@GetMapping("/sign-in/naver")
@Operation(summary = "네이버 로그인 메서드", description = "네이버 로그인을 하기 위한 메서드입니다.")
public void naverLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.sendRedirect(naverService.getAuthorizationUrl());
}

@GetMapping("/sign-in/naver/callback")
@Operation(summary = "네이버 로그인 콜백 메서드", description = "네이버 로그인 콜백을 하기 위한 메서드입니다.")
public TokenDto naverCallback(@RequestParam String code, @RequestParam String state) throws IOException {
TokenDto token = naverService.getNaverToken("token", code);
naverService.saveNaverUser(naverService.getNaverUserByToken(token));
return token;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package org.swmaestro.repl.gifthub.auth.service;

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;
import org.swmaestro.repl.gifthub.auth.dto.TokenDto;
import org.swmaestro.repl.gifthub.auth.entity.Member;
import org.swmaestro.repl.gifthub.auth.repository.MemberRepository;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

@Service
@PropertySource("classpath:application.yml")
public class NaverService {
private final MemberService memberService;
private final MemberRepository memberRepository;
private final String clientId;
private final String state;
private final String responseType;
private final String authorizationUri;
private final String redirectUri;
private final String clientSecret;
private final String tokenUri;
private final String userInfoUri;
private final JsonParser parser = new JsonParser();


public NaverService(MemberService memberService,
MemberRepository memberRepository,
@Value("${naver.client-id}") String clientId,
@Value("${naver.state}") String state,
@Value("${naver.response-type}") String responseType,
@Value("${naver.authorization-uri}") String authorizationUri,
@Value("${naver.redirect-uri}") String redirectUri,
@Value("${naver.client-secret}") String clientSecret,
@Value("${naver.token-uri}") String tokenUri,
@Value("${naver.user-info-uri}") String userInfoUri) {
this.memberService = memberService;
this.memberRepository = memberRepository;
this.clientId = clientId;
this.state = state;
this.responseType = responseType;
this.authorizationUri = authorizationUri;
this.redirectUri = redirectUri;
this.clientSecret = clientSecret;
this.tokenUri = tokenUri;
this.userInfoUri = userInfoUri;
}

public String getAuthorizationUrl() {
return UriComponentsBuilder
.fromUriString(authorizationUri)
.queryParam("client_id", clientId)
.queryParam("response_type", responseType)
.queryParam("redirect_uri", redirectUri)
.queryParam("state", state)
.build().toString();
}

public TokenDto getNaverToken(String type, String code) throws IOException {
URL url = new URL(UriComponentsBuilder
.fromUriString(tokenUri)
.queryParam("grant_type", "authorization_code")
.queryParam("client_id", clientId)
.queryParam("client_secret", clientSecret)
.queryParam("code", code)
.build()
.toString());

HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");

int responseCode = con.getResponseCode();
BufferedReader br;

if (responseCode == 200) { // 정상 호출
br = new BufferedReader(new InputStreamReader(con.getInputStream()));
} else { // 에러 발생
br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
}

String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = br.readLine()) != null) {
response.append(inputLine);
}

br.close();

JsonElement element = parser.parse(response.toString());

return TokenDto.builder()
.accessToken(element.getAsJsonObject().get("access_token").getAsString())
.refreshToken(element.getAsJsonObject().get("refresh_token").getAsString())
.build();
}

public Member getNaverUserByToken(TokenDto token) throws IOException {
String accessToken = token.getAccessToken();

URL url = new URL(userInfoUri);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Authorization", "Bearer " + accessToken);

int responseCode = con.getResponseCode();
BufferedReader br;

if (responseCode == 200) { // 정상 호출
br = new BufferedReader(new InputStreamReader(con.getInputStream()));
} else { // 에러 발생
br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
}

String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = br.readLine()) != null) {
response.append(inputLine);
}

br.close();

JsonElement element = parser.parse(response.toString());

return Member.builder()
.username(element.getAsJsonObject().get("response").getAsJsonObject().get("email").getAsString())
.nickname(element.getAsJsonObject().get("response").getAsJsonObject().get("nickname").getAsString())
.build();
}

public void saveNaverUser(Member member) {
if (!memberService.isDuplicateUsername(member.getUsername())) {
memberRepository.save(member);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class SecurityConfig {
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(authorizeHttpRequests ->
authorizeHttpRequests.requestMatchers("/auth/sign-up", "/auth/sign-in", "/auth/kakao/**", "/auth/google/**",
authorizeHttpRequests.requestMatchers("/auth/sign-up", "/auth/sign-in", "/auth/kakao/**", "/auth/google/**", "/auth/sign-in/**",
"/swagger-resources/**", "/swagger-ui/**", "/v3/api-docs/**", "/webjars/**", "/error").permitAll()
.anyRequest().authenticated())
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,16 @@
import org.swmaestro.repl.gifthub.auth.dto.SignInDto;
import org.swmaestro.repl.gifthub.auth.dto.SignUpDto;
import org.swmaestro.repl.gifthub.auth.dto.TokenDto;
import org.swmaestro.repl.gifthub.auth.entity.Member;
import org.swmaestro.repl.gifthub.auth.service.AuthService;
import org.swmaestro.repl.gifthub.auth.service.MemberService;
import org.swmaestro.repl.gifthub.auth.service.NaverService;
import org.swmaestro.repl.gifthub.auth.service.RefreshTokenService;
import org.swmaestro.repl.gifthub.util.JwtProvider;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

Expand All @@ -43,44 +46,47 @@ public class AuthControllerTest {
@MockBean
private JwtProvider jwtProvider;

@MockBean
private NaverService naverService;

@Test
public void signUpTest() throws Exception {
SignUpDto signUpDto = SignUpDto.builder()
.username("jinlee1703")
.password("abc123##")
.nickname("이진우")
.build();
.username("jinlee1703")
.password("abc123##")
.nickname("이진우")
.build();

TokenDto tokenDto = TokenDto.builder()
.accessToken("myawesomejwt")
.refreshToken("myawesomejwt")
.build();
.accessToken("myawesomejwt")
.refreshToken("myawesomejwt")
.build();


mockMvc.perform(post("/auth/sign-up")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(signUpDto)))
.andExpect(status().isOk());
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(signUpDto)))
.andExpect(status().isOk());
}

@Test
public void signInTest() throws Exception {
SignInDto loginDto = SignInDto.builder()
.username("jinlee1703")
.password("abc123##")
.build();
.username("jinlee1703")
.password("abc123##")
.build();

TokenDto tokenDto = TokenDto.builder()
.accessToken("myawesomejwt")
.refreshToken("myawesomejwt")
.build();
.accessToken("myawesomejwt")
.refreshToken("myawesomejwt")
.build();

when(authService.signIn(any(SignInDto.class))).thenReturn(tokenDto);

mockMvc.perform(post("/auth/sign-up")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(loginDto)))
.andExpect(status().isOk());
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(loginDto)))
.andExpect(status().isOk());
}

@Test
Expand All @@ -92,17 +98,41 @@ public void validateRefreshTokenTest() throws Exception {
String username = "jinlee1703";

TokenDto tokenDto = TokenDto.builder()
.accessToken(newAccessToken)
.refreshToken(newRefreshToken)
.build();
.accessToken(newAccessToken)
.refreshToken(newRefreshToken)
.build();

when(refreshTokenService.createNewAccessTokenByValidateRefreshToken(refreshToken)).thenReturn(null);
when(refreshTokenService.createNewRefreshTokenByValidateRefreshToken(refreshToken)).thenReturn(null);
when(jwtProvider.getUsername(refreshToken)).thenReturn(username);


mockMvc.perform(post("/auth/refresh")
.header("Authorization", refreshToken))
.andExpect(status().isUnauthorized());
.header("Authorization", refreshToken))
.andExpect(status().isUnauthorized());
}

@Test
public void naverSignInCallbackTest() throws Exception {
String accesstoken = "myawesome_accesstoken";
String code = "myawesome_code";
String state = "myawesome_state";
TokenDto token = TokenDto.builder()
.accessToken(accesstoken)
.refreshToken(accesstoken)
.build();
Member member = Member.builder()
.username("[email protected]")
.nickname("이진우")
.build();

when(naverService.getNaverToken("token", code)).thenReturn(token);
when(naverService.getNaverUserByToken(token)).thenReturn(member);

mockMvc.perform(get("/auth/sign-in/naver/callback")
.queryParam("code", code)
.queryParam("state", state)
.header("Authorization", "Bearer " + accesstoken))
.andExpect(status().isOk());
}
}

0 comments on commit 60b83ad

Please sign in to comment.