DEVELOPMENT/PROJECT NOTES

GitHub 로그인 구현? 생각보다 너무 쉽다! (진짜 쉽다…)

Watnu 2024. 12. 19. 18:14

 

GitHub OAuth를 이용하면 소셜 로그인을 쉽게 구현할 수 있습니다.
이 글에서는 GitHub OAuth App을 등록하는 방법부터 로그인 흐름, 구현까지 간단히 정리해 보겠습니다.



01


Github OAuth App 등록하기

1. 설정 메뉴로 이동하기

먼저 GitHub에 로그인한 후, Settings > Developer settings > OAuth Apps로 이동합니다.

 

2. 앱 정보 입력하기

필요한 정보를 입력해 앱을 등록합니다.

  • Application name: 웹사이트 이름
  • HomePage URL: 내 웹사이트 주소
  • Application description: 사이트 설명 (선택 사항)
  • Authorization callback URL: 인증 완료 후 GitHub 인증 서버가 코드를 보낼 URL

모든 정보를 입력한 뒤 Register application 버튼을 클릭하면 앱이 생성됩니다.

 

3. 앱 생성 완료 확인하기

먼저 화면에 보이는 로그인

앱이 성공적으로 생성되면, 아래 정보를 확인할 수 있습니다.

  • Client ID: 생성된 앱의 세부 정보에서 바로 확인 가능
  • Client Secret: Generate a new Client secret 버튼을 클릭하면 발급 가능

 

⚠️ 중요:
Client ID와 Client Secret은 절대 외부에 공개되면 안 됩니다!
만약 노출되면 보안 취약점이 발생할 수 있으니, GitHub나 공개 저장소에 업로드하지 않도록 주의하세요.


02

로그인 흐름 이해하기 

아래는 GitHub OAuth 로그인의 간단한 흐름입니다.

 

 

" GitHub OAuth 로그인의 기본 흐름은 다음과 같습니다. "

  1. 사용자가 GitHub ID로 로그인을 요청합니다.
  2. 사용자는 GitHub 인증 화면으로 리디렉션 됩니다.
  3. 사용자가 로그인을 완료하면, GitHub은 사용자를 귀하의 사이트로 다시 리디렉션 합니다.
  4. 사이트는 사용자의 액세스 토큰(Access Token)을 사용해 API에 접근합니다.

03

로그인 페이지 구현하기

먼저 화면에 보이는 로그인 페이지에서 GitHub로그인 페이지로 넘어가는 부분부터 만들어보겠습니다.

1. OAuth 리디렉션 처리

GitHub OAuth에서는 리디렉션 URL을 사용해 사용자의 인증을 처리합니다.
아래는 GitHub OAuth 엔드포인트와 필요한 매개변수입니다.

https://github.com/login/oauth/authorize?client_id=${GITHUB_CLIENT_ID}&redirect_uri=${GITHUB_REDIRECT_URI}&response_type=code&scope=${GITHUB_SCOPE}

⚠️ 매개변수는 env파일에 넣어 사용하는 걸 권장합니다!

더 자세한 내용은 GitHub의 OAuth 권한 범위 문서를 참고 바랍니다.

쿼리 매개변수 유형 설명 필수인가?
client_id string GitHub OAuth에 등록할 때 받은 클라이언트 ID 필수
redirect_uri string 승인 후 사용자가 전송되는 URL 강력 추천
scope string 애플리케이션에서 요청하는 권한의 범위 지정 문맥에 따라 다름
respone_type string GitHub OAuth 요청에서 응답의 형태를 지정

예를 들어, response_type=code는
"승인 후 내가 사용할 인증 코드만 받아오겠다"는 뜻입니다
OAuth 2.0에서
사용되는 매개변수

2. 로그인 페이지 구성

react-router-dom을 사용하여 Login페이지와 Callback페이지를 라우팅 합니다.

<Route path="/login" element={<Login />} />
<Route path="/login/oauth/callback" element={<Callback />} />

 

3. 로그인 버튼 구현

GitHub 로그인버튼을 클릭하면 Redirect URL을 전달받아 소셜로그인 페이지로 이동되게 합니다.

const { VITE_GITHUB_CLIENT_ID, VITE_GITHUB_REDIRECT_URI, VITE_GITHUB_SCOPE } = import.meta.env;
const GITHUB_AUTH_URL = `https://github.com/login/oauth/authorize?client_id=${VITE_GITHUB_CLIENT_ID}&redirect_uri=${VITE_GITHUB_REDIRECT_URI}&response_type=code&scope=${VITE_GITHUB_SCOPE}`;

const Login = () => {
  return (
    <>
      <button
        onClick={(e) => {
          e.preventDefault();
          window.location.href = GITHUB_AUTH_URL;
        }}
      >
        GitHub 계정으로 로그인
      </button>
    </>
  );
};

 

4. 실행


04

로그인 관련 API

1. Access Token과 Refresh Token 저장

로그인 성공 시 서버에서 받은 Access Token과 Refresh Token을 쿠키에 저장합니다.
이를 위해 react-cookie 라이브러리를 설치합니다.

npm install react-cookie

 

react-cookie 라이브러리를 사용하는 방법은 아래와 같습니다.

  // 쿠키 객체 생성
  const cookies = new Cookies();
  
  // "code"라는 이름으로 쿠키 생성 및 저장
  cookies.set("code", response.data.code, { path: "/" });
  // "code"라는 이름의 쿠키를 삭제
  cookies.remove("code");
  // "code"라는 이름의 쿠키 값을 가져옴
  cookies.get("code");

 

아래처럼 Access Token과 Refresh Token을 쿠키에 저장합니다.

cookies.set("accessToken", response.data.access_token, { path: "/" });
cookies.set("refreshToken", response.data.refresh_token, { path: "/" });

 

 

" 토큰 관련 글"

😊 이미 작성한 토큰 관련 글도 참고하면 좋을 것 같습니다!

 

쿠키? 세션? JWT? 로그인 뒤에 숨어있는 이 복잡한 친구들

회원 기능을 구현하려면 세 가지 주요 방식을 사용할 수 있습니다.첫 번째는 쿠키를 활용한 방식, 두 번째는 세션방식, 그리고 세 번째는 JWT를 이용한 토큰 방식입니다.또한, 구글이나 페이스북

dev-watnu.tistory.com

 

 

2. 인가 코드 처리

GitHub에서 전달받은 인가 코드를 처리하는 단계입니다.

코드를 받아 백엔드로 전달하고, 문제가 발생했을 때는 에러를 처리해야 합니다.

 

GitHub OAuth의 리디렉션 URL에서 code 값을 추출합니다.

const location = useLocation();
const url = new URLSearchParams(location.search);
const code = url.get("code");

 

⚠️ 인가코드가 없는 경우 에러처리

인가코드가 없을 경우 함수를 종료합니다.

if(!code){
  console.error("인가 코드가 없습니다.");
  return;
}

 

3.  로그인 요청

로그인 요청 코드는 아래와 같습니다.

const cookies = new Cookies();

export const login = async (code: string): Promise<LoginResponse> => {
  if (!code) throw new Error("인가 코드가 없습니다.");

  const response = await axios.post<LoginResponse>("/auth/login/", { code });
  cookies.set("accessToken", response.data.access_token, { path: "/" });
  cookies.set("refreshToken", response.data.refresh_token, { path: "/" });
  return response.data;
};

 

⚠️ 쿠키 유효성 확인

서버에 refresh Token값을 주고 새로운 accessToken을 발급받습니다.

const cookies = new Cookies();

export const authCheck = async (): Promise<LoginResponse> => {
  const refreshToken = cookies.get("refreshToken");
  if (!refreshToken) throw new Error("RefreshToken이 없습니다.");

  const response = await axios.post<LoginResponse>("/auth/token/verify/", {
    token: refreshToken,
  });
  cookies.set("accessToken", response.data.access_token, { path: "/" });
  cookies.set("refreshToken", response.data.refresh_token, { path: "/" });
  return response.data;
};

 

유효성 검사는 Custom Hooks로 만들어서 사용성을 높였습니다.

export const useAuthCheck = () => {
  useEffect(() => {
    const checkAuth = async () => {
      try {
        await authCheck();
      } catch (error) {
        console.warn("토큰 유효성 검사 실패:", error);
      }
    };

    checkAuth();
  }, []);
};

 

4. 로그아웃 처

서버에 refresh Token값을 주고 로그아웃을 요청합니다.

해당 Access Token과 Refresh Token 값을 쿠키에서 삭제합니다.

const cookies = new Cookies();

export const logout = async (): Promise<void> => {
  const refreshToken = cookies.get("refreshToken");
  if (!refreshToken) throw new Error("RefreshToken이 없습니다.");

  await axios.post("/auth/logout/", { token: refreshToken });
  cookies.remove("accessToken");
  cookies.remove("refreshToken");
};

05

Callback 페이지

Callback 페이지는 GitHub 인증 후 사용자가 리디렉션 되는 경로입니다.
이곳에서 인가 코드(code)를 추출하고 로그인 절차를 완료합니다.

 

" Callback 페이지 작동 흐름 "

  1. 사용자가 GitHub 인증 페이지에서 로그인을 완료
  2. GitHub이 애플리케이션의 Callback 페이지(URL)로 리디렉션
  3. Callback 페이지가 URL에서 code를 추출
  4. 추출한 code를 서버로 전달해 최종 로그인 완료
export const Callback = () => {
  const navigate = useNavigate();
  const location = useLocation();

  const url = new URLSearchParams(location.search);
  const code = url.get("code");

  useEffect(() => {
    const handleLogin = async () => {
      if (!code) {
        console.error("인가 코드가 없습니다.");
        navigate("/login");
        return;
      }

      try {
        await login(code);
        navigate("/");
      } catch (error) {
        console.error("로그인 실패:", error);
        navigate("/login");
      }
    };

    handleLogin(); // 인가 코드가 있는 경우에만 실행
  }, [code, navigate]);

  return <div>로그인 처리 중...</div>;
};

 


06

실행

  1. 로그인 버튼 클릭 → GitHub 로그인 페이지로 이동
  2. 사용자가 GitHub에서 인증을 완료
  3. GitHub이 Callback 페이지로 리디렉션
  4. 인가 코드를 사용해 Access Token과 Refresh Token 저장
  5. 로그인 성공 후 사용자는 서비스 이용 가능


07

정리

GitHub OAuth를 활용하면 사용자의 비밀번호를 공유하지 않고도 안전하고 편리하게 소셜 로그인을 구현할 수 있습니다.
특히 Access TokenRefresh Token을 활용한 인증 흐름은 보안성과 확장성을 모두 충족시킬 수 있어요.
다만, OAuth 구현 과정에서 Client Secret 관리토큰 보안 같은 세부 사항에 주의를 기울여야 합니다.

이 글이 GitHub OAuth를 이해하고 적용하는 데 유용한 가이드가 되었기를 바랍니다. 😊