티스토리 뷰
2021년 12월 경에 작성한 블로그 글을 이관한 포스트입니다.
✅ 전체적인 OAuth 로그인 방법
💻 네이버 로그인 클라이언트(리액트) 코드
네이버 로그인 JDK 사용하는 방법
로그인 페이지 컴포넌트
import LoginNaver from './LoginNaver';
<LoginNaver />
네이버 로그인 JDK 사용로직
import React, { useEffect } from 'react';
import { naverClientId, naverRedirectURL, naverSecret } from '../../utils/OAuth';
const { naver } = window;
const LoginNaver = () => {
const initializeNaverLogin = () => {
const naverLogin = new naver.LoginWithNaverId({
clientId: naverClientId,
callbackUrl: naverRedirectURL,
clientSecret: naverSecret,
isPopup: false, // popup 형식으로 띄울것인지 설정
loginButton: { color: 'green', type: 3, height: '60' }, //버튼의 스타일, 타입, 크기를 지정
});
naverLogin.init();
};
useEffect(() => {
initializeNaverLogin();
}, []);
return <div id='naverIdLogin' />;
};
export default LoginNaver;
반환값
http//리다이렉트 설정 url ? access-token = {토큰값} & state = {스테이트 값} & token-type = {토근타입} & expire = {만료기간}
네이버 로그인 REST API 사용하는 방법
a태그에
https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=
{클라이언트아이디}&state={임의값 사용}&redirect_uri={등록한 리다이렉트 URL}
를 넣어 네이버로그인페이지로 이동시켜줍니다. 그리고 로그인이 완료되면 설정해놓은 리다이렉트 주소로 URL에 code값과 state값이 넘어옵니다.
📢 여기서 중요한 점 !!!
네이버 JDK로 로그인을 클라이언트에서 하게되면 리다이렉트로 넘겨주는 토큰은 일회성토큰이 아니라 바로 사용할 수 있는 접근토큰입니다.
따라서 서버에서 사용자 프로필정보를 바로 요청할 수 있습니다.
(이거 몰라서 해당 토큰으로 토큰발급 api 작동해서 엄청 고생했습니다...)
반대로 REST API로 클라이언트에서 요청한 경우에는 일회성토큰이므로 서버에서 한번 더 토큰발급을 해당 일회성 토큰으로 발급하고 프로필정보요청 API를 사용해야합니다.
네이버 로그인 JDK 서버 처리 로직 (Spring)
public void naverToken(String code, HttpServletResponse response) throws IOException {
try {
JSONParser jsonParser = new JSONParser();
String header = "Bearer " + code;
Map<String, String> requestHeaders = new HashMap<>();
requestHeaders.put("Authorization", header);
String responseBody = get(NAVER_USER_INFO_URI, requestHeaders);
JSONObject parse = (JSONObject) jsonParser.parse(responseBody);
JSONObject responseParse = (JSONObject) parse.get("response");
String encodeUserName = (String) responseParse.get("name");
String loginId = (String) responseParse.get("id");
String email = (String) responseParse.get("email");
String phoneNumber = (String) responseParse.get("mobile_e164");
String userName = new String(encodeUserName.getBytes(StandardCharsets.UTF_8));
User user = new UserRequest("social_" + loginId, userName, encode.encode("네이버"), email, phoneNumber).naverOAuthToEntity();
if (userRepository.existsByLoginId(user.getLoginId()) == false) {
userRepository.save(user);
}
String access_token = tokenProvider.create(new PrincipalDetails(user));
response.addHeader("Authorization", "Bearer " + access_token);
} catch (Exception e) {
e.printStackTrace();
}
}
💻 카카오 로그인 클라이언트(리액트) 코드
카카오는 REST API로만 구현해서 해당 부분만 포스팅하겠습니다.
// 변수처리를 위한 다른 JS 파일
export const KAKAO_AUTH_URL = `https://kauth.kakao.com/oauth/authorize?client_id=${kakaoClientId}&redirect_uri=${kakaoRedirectURL}&response_type=code&prompt=login`;
// 로그인 페이지 해당 코드
<KakaoBtn href={KAKAO_AUTH_URL}>
<img src={`${process.env.PUBLIC_URL}/images/kakao_login_large_narrow.png`} alt='kakaoLogin' />
</KakaoBtn>
반환값
`http//리다이렉트 설정 url?code={일회성 토큰값}`
별다른 state값을 로그인 요청시 url에 넣어주지 않았다면 state값은 선택사항이라 넘어오지 않을 것이다. 문서보고 헷갈리지 말자!
📢 여기서 중요한 점 !!!
이부분은 REST API를 사용했기 때문에 일회성토큰이 클라이언트로 넘어옵니다. 따라서 해당 토큰을 가지고 서버에서 한번 더 정식 토큰 발급을 요청하고 넘어온 access-token으로 사용자프로필 조회 API를 작동해야 오류가 나지 않습니다!!
또한, contentType이 올바른지 꼭 확인하세요!
제 경우에는 ContentType -> application/json로 멋대로 json으로 요청을 보냈다가
org.springframework.web.client.HttpClientErrorException$Unauthorized: 401 Unauthorized: [no body]
위와 같은 에러가 났으니 꼭 !!!
ContentType은 application/x-www-form-urlencoded;charset=utf-8 공식문서대로 진행해서 요청해주세요!!
카카오 로그인 Rest API 서버 처리 로직 (Spring)
public void kakaoToken(String code, HttpServletResponse res, HttpSession session) {
RestTemplate rt = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
MultiValueMap<String, String> accessTokenParams = accessTokenParams("authorization_code",KAKAO_CLIENT_ID ,code,KAKAO_REDIRECT_URI);
HttpEntity<MultiValueMap<String, String>> accessTokenRequest = new HttpEntity<>(accessTokenParams, headers);
ResponseEntity<String> accessTokenResponse = rt.exchange(
KAKAO_TOKEN_URI,
HttpMethod.POST,
accessTokenRequest,
String.class);
try {
JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject) jsonParser.parse(accessTokenResponse.getBody());
session.setAttribute("Authorization", jsonObject.get("access_token"));
String header = "Bearer " + jsonObject.get("access_token");
System.out.println("header = " + header);
Map<String, String> requestHeaders = new HashMap<>();
requestHeaders.put("Authorization", header);
String responseBody = get(KAKAO_USER_INFO_URI, requestHeaders);
JSONObject profile = (JSONObject) jsonParser.parse(responseBody);
JSONObject properties = (JSONObject) profile.get("properties");
JSONObject kakao_account = (JSONObject) profile.get("kakao_account");
Long loginId = (Long) profile.get("id");
String email = (String) kakao_account.get("email");
String userName = (String) properties.get("nickname");
User kakaoUser = new UserRequest("social_" + loginId, encode.encode("카카오"), userName, email).kakaoOAuthToEntity();
if (userRepository.existsByLoginId(kakaoUser.getLoginId()) == false) {
userRepository.save(kakaoUser);
}
String access_token = tokenProvider.create(new PrincipalDetails(kakaoUser));
res.setHeader("Authorization", "Bearer "+access_token);
} catch (Exception e) {
e.printStackTrace();
}
}
몇가지 추가 당부
1. 로그인페이지로 이동할 수 없다면 네이버, 카카오 개발자 페이지에서 내 어플리케이션 도메인 서비스 url에 개발중인 클라이언트 주소가 넣어져있는지 확인하자(ex : http//localhost:3000)
2. 서버에서 에러가 난다면 필수 param값을 빠뜨렸는지 확인한다.
3. 401에러가 난다면 contentType이 올바른지, 혹시 보안설정을 추가로 해서 secret값을 추가로 넣어야하는지 확인하자.
참조
이미지 참고
'개발' 카테고리의 다른 글
웹 성능 최적화 : Dynamic Import로 js 코드 스플릿하기 (1) | 2023.10.24 |
---|---|
우리도 해보자 : MFA(Micro Frontend Architecture) 도입기 with Module Federation (1) | 2023.10.24 |
PnP 그리고 Yarn berry가 뭐길래 쓰는지 이제 알아보자 (0) | 2023.10.24 |
Vue3 setup에서 defineProps 사용하기 With Typescript (0) | 2023.10.23 |
Vue에서 scoped된 컴포넌트의 하위로 scss 스타일을 강제로 줘보자!(::v-deep, :deep) (0) | 2023.10.23 |
- Total
- Today
- Yesterday
- deploy
- 당신은 결국 무엇이든 해내는 사람
- pnpm
- TanStackQuery
- node module
- defineProps
- DevOps
- Style
- subrouting
- Infra
- design system
- vue3
- Flutter
- Micro Frontend Architecture
- CI
- 상태관리전략
- error handle
- 독후감
- vue
- 프론트엔드최적화
- Module Federation
- test
- frontend
- zero install
- yarn-berry
- 프론트엔드아키텍처
- MFA
- 서버상태관리
- aws
- 독서
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |