본문 바로가기
기억 저장소

[Node.js] 초간단 Github OAuth 인증 구현

by halls99 2022. 10. 2.

🔥 결과

 

 

이렇게 Github로 로그인 버튼을 누르면 인증 과정을 거쳐 사용자의 정보를 가져올 수 있다.

 

전체 코드는 하단 Github Repository 링크를 첨부했다.

 

 


🌠 환경

 

  "dependencies": {
    "axios": "^0.27.2",
    "cookie-parser": "~1.4.4",
    "dotenv": "^16.0.3",
    "express": "~4.16.1",
    "pug": "2.0.0-beta11"
  }

 

Express로 서버 포트를 열고 클라이언트 단에서 axios로 통신하는 매우 간단한 환경이다.

 

🔹 서버 파일

 

  • app.js
    • nodemon으로 가장 먼저 실행되는 파일로, express 미들웨어 설정과 router 호출을 담당
  • routers/index.js
    • 메인 페이지를 라우팅
  • routers/oauth.js
    • github oauth 관련 페이지를 라우팅
  • utils.js
    • github oauth 관련 유틸 함수들 모음
  • constants.js
    • 상수 관리 파일

🔹 클라이언트 파일

 

  • views/index.pug
    • routers/index.js에 의해 랜더링 되는 메인 페이지
  • public/javascripts/index.js
  • public/stylesheets/style.css

 

 

 


🌊 흐름

 

 

✅ 1. 로그인 이벤트 발동

  // index.js
  $loginBtn.addEventListener("click", () => {
    location.href = "/github-oauth";
  });

 

Github로 로그인 버튼을 누르면 페이지 이동이 일어난다.

 

 

 

 

✅ 2. Github OAuth 페이지에 요청

 

// app.js
app.use("/github-oauth", oauthRouter);

 

페이지 이동을 Express 라우터가 잡는다.

 

 

 

Github OAuth 명세에 나와있듯이,

 

위 링크를 url로, Required 마킹이 되어있는 client_id 를 param으로 설정해서 요청했다.

 

// routers/oauth.js
router.get("/", function (req, res, next) {
  const url = URL.github_authorization;
  const client_id = GITHUB_DATA.client_id;
  const param = new URLSearchParams({ client_id }).toString();
  res.redirect(`${url}?${param}`);
  next();
});
...

 

 

 

 

✅ 3. 인증 -> Authorization Code

 

 

위 화면은 Github로 로그인 버튼을 누르면 나오는 페이지이다.

 

사용자가 Authorize 버튼을 누르면 url query에 담긴 Authorization Code 발급과 함께 Callback이 일어난다.

 

 

// routers/oauth.js
router.get("/callback?*", async function ({ query: { code } }, res, next) {
  const accessToken = await getAccessTokenByAuthorizationCode(code);
  const { name, public_repos } = await getUserDataByAccessToken(accessToken);
  const userData = { userName: name, userRepo: public_repos };
  res.cookie("userData", userData);
  res.redirect("/");
  next();
});

 

 

위 코드는 Callback 요청을 라우터가 잡아서 실행되는 코드이다.

 

이어지는 설명은 utils.js에서 import 하여 사용한 2개의 메서드가

어떻게 Authorization Code를 사용자 정보로 바꾸는지에 대한 과정이다.

 

 

 

 

✅ 4. Authorizaion Code -> Access Token

 

//utils.js
async function getAccessTokenByAuthorizationCode(code) {
  return await axios({
    method: METHOD.post,
    url: URL.github_access_token,
    headers: {
      accept: "application/json",
    },
    data: {
      client_id: GITHUB_DATA.client_id,
      client_secret: GITHUB_DATA.client_secret,
      code: code,
    },
  }).then((res) => res.data.access_token);
}

 

 

url query에서 뽑아낸 Authorization Code를 인자로 받아서 Access Token 요청한다.

 

 

 

맨 처음 Authorization 요청을 할 때와 마찬가지로, 위 주소를 url로 하고

 

Required 마킹된 client_id, client_secret, codedata로 설정하여 POST 요청을 보냈다.

 

 

 

 

 

✅ 5. Access Token -> userData

 

 

// utils.js
async function getUserDataByAccessToken(accessToken) {
  return await axios({
    method: METHOD.get,
    url: URL.github_user_api,
    headers: {
      Authorization: `token ${accessToken}`,
    },
  }).then((dataObject) => dataObject.data);
}

 

 

마찬가지로 위 주소를 url로 하여 headersAccess Token을 담아서 요청을 보냈다.

 

 

 

 

✅ 6. 사용자 정보 추출

 

// routers/oauth.js
router.get("/callback?*", async function ({ query: { code } }, res, next) {
  const accessToken = await getAccessTokenByAuthorizationCode(code);
  const { name, public_repos } = await getUserDataByAccessToken(accessToken);
  const userData = { userName: name, userRepo: public_repos };
  res.cookie("userData", userData);
  res.redirect("/");
  next();
});

 

다시 3번 과정의 callback 이후 실행되는 코드이다.

 

사용자의 Github 정보(userData)가 응답으로 반환되면 위 코드처럼 원하는 정보만 가져와 사용할 수 있다.

 

name, public_repo 말고도 email, followers, 다양한 url들을 가져올 수 있다.

 

일단 사용자 정보를 메인 페이지에서 랜더링 하기 위해 cookie에 담았다.

 

 

 

 

 

✅ 7. 사용자 정보 랜더링

  

// routers/index.js
router.get("/", function (req, res, next) {
  let dataObject = {};
  // Github OAuth 로 받아온 유효한 사용자의 정보가 있다면 화면에 표시
  const isUserDataExist = req.cookies.userData !== undefined;
  if (isUserDataExist) {
    const { userName, userRepo } = req.cookies.userData;
    dataObject = { userName, userRepo };
  }
  res.render("index", { ...dataObject });
  next();
});

 

메인 페이지는 cookie를 보며 userData가 있다면 화면에 표시하도록 한다.

 

 

 


Github Repository 링크

 

https://github.com/edac99/github-oauth-nodejs

 

edac99/github-oauth-nodejs

Github OAuth with NodeJS and Express.js. Contribute to edac99/github-oauth-nodejs development by creating an account on GitHub.

github.com

 

 

댓글