[개발심화] OAuth - 7주차 (5)

Hong·2022년 10월 29일
0
post-thumbnail




🔐 OAuth란?

우리가 A라는 사이트에 로그인 할 때 구글을 이용해 로그인 하시겠습니까?버튼을 눌러서 구글을 통해 A사이트를 로그인 할 수 있게 만드는 기술임

왜 사용하는가?

User입장에서 매 사이트마다 id, password를 만들어도 되지 않으니 편하기도 하고
App client에서 OAuth방식을 이용해서 로그인 할 경우 App client에 id, password가 노출될 일도 없어서 보안 상으로도 이점이 있는 기술임



OAuth가 없을 경우 user가 client에게 id, password를 위임하고 client가 resource server에 유저 정보를 요청하는 매커니즘

(사전작업) client app은 resource server로 부터 id와 secret password를 가져온다(resource server입장에서 client에게 라이센스를 부과하는 과정과 같음)
2. user(resource owner)가 client app에 본인의 id와 password를 맡기고 client는 server에 resource owner의 정보를 요청한다


OAuth가 있을 경우 client가 resource server에 유저 정보를 요청하는 매커니즘

(사전작업) client app은 resource server로 부터 id와 secret password를 가져온다(client입장에서 resource server에게 라이센스를 부과하는 과정과 같음)
1. user는 client app페이지로 로그인을 시도한다
2. client app은 user interface화면에 '구글로 로그인 하시겠습니까?'라는 화면을 띄운다
3. '동의'버튼을 누르면 user는 client app에서 자동적으로 구글로 접속된다(user가 직접 구글로 접속하는 것과 같음)
4. 구글은 client app에게 user가 동의했음을 authorization code를 전달함으로써 알려준다
5. client app은 본인이 원래 들고 있던 라이센스(id, scret password)와 구글로부터 전달받은 code(user가 정보제공에 동의했음을 증명하는 물건)를 구글로 보내준다
5-1. 구글은 id, secret password, code를 합쳐서 이 client app이 라이센스를 받은 안전한 사용자인지, user의 정보제공은 받았는지 판단한다
5-2. 구글은 client app에게 access token을 발행한다 (만약 client app으로부터 받은 모든 데이터가 유효하다면)
6. client app은 전달받은 access token을 가지고 구글에 접속한다
7. 구글은 client app에게 요청한 data를 제공한다
8. client app은 user에게 뽑아온 데이터를 제공한다(raw data를 전달하지 않고 가공된 데이터를 전달하는 것도 가능)

참고

https://www.youtube.com/watch?v=PIlP_YX5HK8


Q) access token이 만료되면 어떻게 해야할까?

Refresh Token Grant Type을 통해 재발급 받아야 함




👾 코드를 통해 알아보자

Server입장에서 Authorization Server(여기서는 github)에 post요청으로 id, secret, code를 보내서 access token을 받아오기 위한 프로세스를 처리하는 모듈이다

require('dotenv').config();

const clientID = process.env.GITHUB_CLIENT_ID;
const clientSecret = process.env.GITHUB_CLIENT_SECRET;
const axios = require('axios');

module.exports = (req, res) => {
  console.log(req.body);


  //우리는 client app으로써 github이라는 Authorization Server에 clientId, clientSecret, code를 post함으로써 access token을 발급받고 싶은 상황이다
  axios({
    method: 'post',
    url: `https://github.com/login/oauth/access_token`,
    headers: {
      "Content-Type": "application/json", //Content-Type을 데이터를 어떤 형태로 보내겠다고 말하는 부분이다 json으로 보내겠다고 했다
      accept: 'application/json', //accpet는 데이터를 어떤 형태로 받겠다고 말하는 부분이다 json으로 받겠다고 했다
    },
    data: {
      client_id: clientID,
      client_secret: clientSecret,
      code: req.body.authorizationCode
    }
  })
    .then((data) => {
      //console.log(data); 를 통해서 data에 어떤 값들이 들어오는지 파악할 수 있다 이것을 통해 data.data에 access_token이 존재함을 찾을 수 있다 (code, id, secret을 보내고 access code를 받아온거임)
      const accessToken = data.data.access_token;
      return res.status(200).send({accessToken : accessToken}) //app client에게 accessToken을 전송해준다
    })
    .catch((err) => {
      return res.status(400)
    })
}

받아온 access token을 통해 resource server에 접속해서 user에게 필요한 데이터를 전달하는 프로세스를 처리하는 모듈이다

const images = require('../resources/resources');

module.exports = (req, res) => {
  //이 모듈은 callback모듈을 통해 들어온 access token이 정상적인 경우와 정상적이지 않은 경우의 분기를 나눠서 코드를 작성해야한다
  //1. accessToken이 정상적으로 존재하다면 resource server의 images를 client에게 전달한다
  //2. accessToken이 정상적으로 존재하지 않는다면 에러 메세지를 보내준다

  // console.log(req.headers.authorization); 를 통해서 req.headers에 authorization안에 access token인 'fake_auth_code'가 있음을 알 수 있다
  /*
  근데 찾을 때 주의해야할 사항은 객체가

  [Symbol(kHeaders)]: {
    host: '127.0.0.1:53246',
    'accept-encoding': 'gzip, deflate',
    authorization: 'token fake_access_token',
    connection: 'close'
  }

  이런 식으로 표현되어 있다 그래서 우리는 저 안에 앞의 k값을 제외한 req.headers로 들어가면 authorization에 접근할 수 있다
  */

  if(req.headers.authorization) {
    return res.status(200).send({images : images}).end()
  } else {
    return res.status(403).json({message : "no permission to access resources"}).end()
  }
}



또 새벽 2시다 자자💤

profile
Notorious

0개의 댓글