Authentication vs Authorization

Authentication

Authentication

유저가 있을 때, 이 유저가 진짜 유저인지 인증하는 것

Authorization

Authorization

유저가 있을 때, 이 유저가 특정 자원에 접근할 권한이 있는지 확인하는 것

예시로, 실제로나 영화에서나 건물의 특정 제한 구역에 Authorized Personnel Only 라는 문구가 붙어있는걸 볼 수 있다.

건물을 들어가는건 등록된 사용자 인증(Authenticatation)을 통해 들어갈 수 있고, 건물 내의 특정 건물은 권한 검사(Authorization)를 통해 들어갈 수 있다.

OAauth

OAuth의 용어들

  • Resource Owner

    보호된 리소스에 대한 접근 권한을 부여할 수 있는 개체

    ex) 자원을 소유하고 있는 사람

  • Client

    Resource OWner를 대신하여 권한을 부여받아 리소스를 요청하는 응용 프로그램

    ex) 개발자가 만들고 있는 서비스

  • Authorization Server

    Resource Owner를 인증하고 권한을 얻은 후 Client에 Access Token을 발급하는 서버

    인증을 담당하는 서버

    ex) GitHub, Google 등의 인증 서버

  • Resource Server

    Access Token을 사용하여 보호된 자원 제공

    ex) GitHub, Google 등의 데이터 서버

OAuth를 쓰는 이유

  • 인증과 권한 부여를 동시에 할 수 있음

    OAuth의 ‘Auth’는 ‘Authentication’과 ‘Authorization’이다.

    Resource Owner가 Client의 정보를 가지고 Authorization Server에 로그인 한다.

    그 결과로 Client는 Resource Owner의 권한(Authorization)을 가지고 Resource에 접근하여 사용자 정보를 확인 후 Authenticate 할 수 있다.

  • Resource Owner(사용자) 입장에서 안전함

    사용하려고 하는 서비스가 나의 어떤 자원을 접근하려고 하는지 확인 가능

  • 서비스 제공자 (클라이언트)의 보안 부담감 낮아짐

    보안에 민감한 사용자의 리소스(ex. PW)를 직접 관리하면 보안에 매우 신경써야함.

OAuth의 절차

+--------+                               +---------------+
|        |--(A)- Authorization Request ->|   Resource    |
|        |                               |     Owner     |
|        |<-(B)-- Authorization Grant ---|               |
|        |                               +---------------+
|        |
|        |                               +---------------+
|        |--(C)-- Authorization Grant -->| Authorization |
| Client |                               |     Server    |
|        |<-(D)----- Access Token -------|               |
|        |                               +---------------+
|        |
|        |                               +---------------+
|        |--(E)----- Access Token ------>|    Resource   |
|        |                               |     Server    |
|        |<-(F)--- Protected Resource ---|               |
+--------+                               +---------------+

출처 : https://tools.ietf.org/html/rfc6749

Code로 알아보는 OAuth 절차

router.get("/github", (req, res) => {
  // (A) Client가 Resource Owner의 GitHub에 대한 권한 부여 요청
  res.redirect(
    `https://github.com/login/oauth/authorize?client_id=${process.env.GITHUB_OAUTH_CLIENT_ID}`
  );
  // (B) 사용자는 GitHub에 로그인하며 Client에게 권한 부여
});
router.get("/github/callback", async (req, res, next) => {
  // req.query에는 Authorization Server에서 제공한 Authorization Code가 들어있음
  if (req.query.error) {
    // GitHub Authorization 실패 (Resource Owner가 GitHub 로그인 실패 또는 권한 부여 거부)
    return;
  }
  const accessCode = req.query.code;
  // (C) 부여된 권한(Authorization Code)을 가지고 Authorization Server에 Access Token 요청
  const accessResponse = await fetch(
    `https://github.com/login/oauth/access_token?client_id=${process.env.GITHUB_OAUTH_CLIENT_ID}&client_secret=${process.env.GITHUB_OAUTH_CLIENT_SECRET}&code=${accessCode}`,
    {
      method: "POST",
      headers: {
        accept: "application/json",
      },
    }
  );
  const accessResponseBody = await accessResponse.json();
  // (D) AccessToken 획득
  const accessToken = accessResponseBody.access_token;

  // (E) Access Token을 가지고 Resource Server에 자원 요청
  const profileResponse = await fetch("https://api.github.com/user", {
    headers: {
      Authorization: `Bearer ${accessToken}`,
      accept: "application/json",
    },
  });
  // (F) 사용자 정보 획득
  const profile = await profileResponse.json();

  res.json(profile);
});

module.exports = router;

Access Token을 획득하는 방법

Authorization Grant (C) 과정을 위해 Resource Owner의 권한을 이용하여 Access Token을 얻는 방법은 4가지가 존재한다.

  • Authorization Code

    • Client는 Resource Owner를 Authorization Server로 리다이렉트 하고 Authorization Server는 인증 코드와 함께 Resource Owner를 클라이언트로 리다이렉트

    • 가장 기본적인 방법 (위에서 구현한 방법)

    • Authorization Code로 브라우저 기반 로그인을 구현하고 싶다면 (A), (B) 과정을 Client에서 popup을 띄워 처리하고 Access Code를 서버에게 넘겨주고 처리하는 방법을 사용할 수 있다.

  • Implicit

    • 브라우저 기반으로 직접 Access Token를 획득하는 방법

      1. Resource Owner는 브라우저 등을 통해 Access Token을 바로 획득하여 Client에게 전달

      2. Client는 Access Token을 받아 Resource Server에 접근

    • Access Code를 얻는 과정을 생략하기 때문에 효율성이 향상되지만 Access Token이 노출되고 Access Token을 가지고 있으면 누구나 자원에 대한 접근이 가능하기 때문에 보안상 좋지 않다.

  • Resource Owner Password Credentials

    • 사용자 아이디, 패스워드를 이용하여 직접 Access Token을 획득

    • Resource Owner와 Client간 신뢰도가 매우 높을 경우 사용

  • Client Credentials

    • Client가 관리하는 자원에 접근하거나 이전의 권한에 따라 자원에 접근할 때 사용

    • 보통 Resource Owner === Client인 경우 사용