https://heokknkn.tistory.com/54
지난편은 여기서 확인해주세요 !!!!
자 ! 저번에 밑에와 같은 화면에서 끝났는데요 !! 바로 이어서 시작해보겠습니다 !
아래에서는 리액트 쿼리에 대한것들도 있는데 이 부분끝나고 바로 다뤄볼게요 !!!!
딱 필요한 부분만 가져와서 설명하겠습니다 !
먼저 저희는 code가 필요합니다 ! 어떻게 가지고 올까요?
useLocation()와 URLSearchParams, code를 이용해서 손쉽게 code를 빼올 수 있습니다.
code를 가져오는 방법은 다양하지만 저는 이 방법으로 가져왔어요 !!
import { useLocation, useNavigate } from "react-router";
export default function GithubConfirm() {
const { search } = useLocation();
const confirmLogin = async () => {
const params = new URLSearchParams(search);
const code = params.get("code");
if (code) {
mutation.mutate(code);
}
};
useEffect(() => {
confirmLogin();
}, []);
}
자 ! 저렇게 해주시고 mutation을 알아봐야겠죠??
전 요번에 tanstack를 이용해서 useMuation기능을 이용했습니다 !!! 사용해보니 너무 편하더라구요 !!
useMutation을 이용해서 성공하면 onSuccess를 ! 실패하면 onError을 !!!
기본적으로 useMutation는
useMutation(mutationFn, options);
mutationFn (variables: TVariables) => Promise<TData>
Required 필수 !
비동기 작업을 수행하고 프로미스를 반환하는 함수입니다 ! (쉽게 말해 api 요청하는 함수)
이정도만 알고 넘어가주세요 이번편에서는요 !
혹시라도 위에처럼 안하시거나 그러시다면 그냥 비동기를 이용해서 서버단으로 request를 해서 state를 관리하셔도 괜찮습니다 !!
또한 useQueryClient를 이용해서 useMuation에서 성공을 하면 refetchQueryies를 해줘서 서버단에서 가져온 정보를 바로 넣어줍니당 ! 또한 성공하고 나서는 redirect도 시켜주죠 !!
다음에 사용 방법에 대해서 다뤄보려고 하는데 혹시라도 지금 당장 위에 부분은 이해 안가시면 댓글 달아주세요 !!!!
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { githubLogIn } from "../api";
import { useToast } from "@chakra-ui/react";
import { useForm } from "react-hook-form";
import { useNavigate } from "react-router";
export default function GithubConfirm() {
const toast = useToast();
const queryClient = useQueryClient();
const navigate = useNavigate();
const { reset } = useForm();
const mutation = useMutation(githubLogIn, {
onSuccess: (data) => {
toast({
status: "success",
title: " Welcome!!!",
description: "Happy to have you back!!",
position: "bottom-right",
});
reset();
queryClient.refetchQueries(["me"]);
navigate("/");
},
onError: (error) => {
console.log("error");
toast({
status: "error",
title: "Login fail",
description: "Check your Github information",
position: "bottom-right",
});
},
});
}
GibhubLogin
export const githubLogIn = (code: string) => {
return axios
.post(`http://127.0.0.1:8000/api/v1/users/github`, { code })
.then((response) => response.status);
};
자 여기까지가 프론트입니당 !!
그러면 백엔드로 넘어가봅시다 !
먼저 저렇게 url하나 만들어주시구요 !!! 전 참고로 ! http://127.0.0.1:8000/api/v1/users/github 이런식입니당 !
먼저 위에 공식문서를 봐주셔야합니다 !!
저희는 서버단으로 code를 넘겨줬습니다 !! 이것을 가지고 다시 서버쪽에서는 POST로 github에 요청을 보내야하죠 !!!
https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps
요기 참고 !
저기서 가장 중요한것은 client_id, client_secret, code 입니당 !
client_id란 code는 저번에 구해오는것을 알았는데 client_sercret는 어디서 할까요???
redirect_uri는 해주시려면 해도 되고 안해도 됩니다 ^^ ( 저는 프론트에서 할거라서요 ! )
자 ! 저번에 만들었던 곳에서 할 수 잇습니다 !!
한번 다운로드 받고 새로고침이라던가 다시 돌아오면 없어지니
서버쪽에서 env파일로 관리하면 좋아요 !!
자 이렇게 하면 준비물은 끝 !!!
그럼 전체적인 코드를 봐볼까요?
def post(self, request):
try:
code = request.data.get("code") # 프론트에서 보내준 code로 access_token을 구해와야한다 !!
access_token = requests.post(
f"https://github.com/login/oauth/access_token?code={code}&client_id=0d776929a7852cb9c693&
client_secret=ca4ee34e324d4c87bb94e6c499029e4512a5e71c",
headers={"Accept": "application/json"},
)
access_token = access_token.json().get("access_token")
# 밑에는 기본적인 user data ( not include email)
user_data = requests.get(
"https://api.github.com/user",
headers={
"Authorization": f"Bearer {access_token}",
"Accept": "application/json",
},
)
user_data = user_data.json()
# 위에서 email이 없었으니 밑에서 불러오자 !
user_emails = requests.get(
"https://api.github.com/user/emails",
headers={
"Authorization": f"Bearer {access_token}",
"Accept": "application/json",
},
)
user_emails = user_emails.json()
try:
user = User.objects.get(email=user_emails[0]["email"])
login(request, user)
return Response(status=status.HTTP_200_OK)
except User.DoesNotExist:
user = User.objects.create(
username=user_data.get("login"),
email=user_emails[0]["email"],
name=user_data.get("name"),
avatar=user_data.get("avatar_url"),
)
user.set_unusable_password() # github로그인이니까 No password!
user.save()
login(request, user)
return Response(status=status.HTTP_200_OK)
except Exception:
return Response(status=status.HTTP_400_BAD_REQUEST)
이렇게 짧게 끝납니다 ! 그러면 하나씩 알아보겠습니다 !
우선 이 부분입니다 !
위에 공식문서에서도 봤듯이 code, client_id, client_secret는 필수입니다 !
참고로 !! client_secret는 정말 중요한 키니까 꼭 안보이게 해주세요 !!! (env파일이라던가 준비해주세요 !!! 전 공개한 이유가 어차피 사용하고 지울거라서요 ! ) 즉 ! 밑에 주석친것처럼 저런식으로요 ^^
그렇게 하고 headers를 json형식으로 해줘서 response 받을 때 json형식으로 받자구요 !
code = request.data.get("code") # 프론트에서 보내준 code로 access_token을 구해와야한다 !!
access_token = requests.post(
f"https://github.com/login/oauth/access_token?code={code}&client_id=0d776929a7852cb9c693&
client_secret=ca4ee34e324d4c87bb94e6c499029e4512a5e71c",
#f"https://github.com/login/oauth/access_token?code={code}&client_id=0d776929a7852cb9c693&
client_secret={settings.GH_LOCAL_SECRET}",
headers={"Accept": "application/json"},
)
자 ! 위에서 access_token을 가지고 왔으니
이번엔 그것을 가지고 user_data를 가져와봅시다 !!!
특히 Authorization 부분은 꼭 저렇게 해주세요 !!!
아래에선 requests를 꼭 import해주시구요 !
access_token = access_token.json().get("access_token")
# 밑에는 기본적인 user data ( not include email)
user_data = requests.get(
"https://api.github.com/user",
headers={
"Authorization": f"Bearer {access_token}",
"Accept": "application/json",
},
)
그리고 나서 한번 로그를 찍어보세요 !! 엄청나게 많은 데이터를 가지고 온답니다 !!!
중요한 정보도 있으니 사진으로는 남기진 않을게요 ㅜㅜ
하지만 ! 저는 이메일을 찾아야합니다 !!! 이메일을 가지고 유저 체크를 하기 위해서입니다 !!!
github의 경우에는 따로 email을 찾는 코드를 추가해야합니다 !
밑에처럼 해주세요 !
user_emails = requests.get(
"https://api.github.com/user/emails",
headers={
"Authorization": f"Bearer {access_token}",
"Accept": "application/json",
},
)
user_emails = user_emails.json()
자 ! 나머진 기존에 장고방식대로 로그인을 하는것입니다 !
유저가 있으면 로그인 시키고 없으면 회원가입을 시키는것이죠 ! 필요한거만 가지구요 !!!
그리고 또한 유의할 점이 ! 어디까지나 github로 회원가입 및 로그인을 시키는거니까 password가 필요없겠죠???
그래서 아래처럼 set_unusable_password를 해줬습니다 !
try:
user = User.objects.get(email=user_emails[0]["email"])
login(request, user)
return Response(status=status.HTTP_200_OK)
except User.DoesNotExist:
user = User.objects.create(
username=user_data.get("login"),
email=user_emails[0]["email"],
name=user_data.get("name"),
avatar=user_data.get("avatar_url"),
)
user.set_unusable_password() # github로그인이니까 No password!
user.save()
login(request, user)
return Response(status=status.HTTP_200_OK)
자 이제 끝입니다 !! 고생하셨습니다 ㅜㅜㅜㅜㅜ
그러면 이제 화면에서만 한번 확인해볼까요???
먼저 장고쪽 admin쪽입니다 !
그럼 회원가입 버튼을 누르고 다시 이 화면을 본다면 ?
전 참고로 프론트쪽에서 onsuccess하면 리다이랙트로 home화면으로 가게 합니당 ^^
짠 !!! 유저 추가 완료 !!!
다들 너무 고생하셨습니다 !! 길긴 했지만 생각보다 쉬웠다고 생각합니다 !!
마지막으로 정리만 하고 넘어갑시당 !!!
첫번째 https://github.com/login/oauth/authorize 여기로 client_id와 scope를 사용해서 1회용성 code를 가져와야합니다 !
두번째 서버에서 https://github.com/login/oauth/access_token 여기로 code를 이용해서 access_token을 구해야합니다 !
세번째 https://api.github.com/user이쪽으로 access_token을 가지고 user_date 및 이메일을 구해서 사용하세요 !
자 ! 이제 손쉽게 자신의 사이트에서도 gibhub로그인을 사용해보자구요 !!! ^^
그리고 여기서 처음 나온
카카오 로그인이나 리액트 쿼리, env파일 만들고 사용하기 같은것들은 추후에 쓸거니 기대해주세요 !!!
'IT관련 > Python' 카테고리의 다른 글
Django와 React를 이용해서 카카오(kakao) 로그인을 해봅시다 !(OAuth) 2편 (0) | 2023.01.28 |
---|---|
Django와 React를 이용해서 카카오(kakao) 로그인을 해봅시다 !(OAuth) 1편 (0) | 2023.01.23 |
Django와 React를 이용해서 github 로그인을 해봅시다 !(OAuth) 1편 (0) | 2023.01.07 |
[Django]drf의 IsAuthenticatedOrReadOnly와 IsAuthenticated의 차이점에 대해서 알아봅시다 ! (0) | 2022.12.12 |
[Django] ModelSerializer vs Serializer의 차이점과 사용법에 대해서 알아봅시다 ! (0) | 2022.11.28 |