간단하게 Oauth를 사용해보는 것을 목적으로 한 포스팅입니다.

용어

  • Resource Owner: 사용자
  • Resource Server: 사용자의 정보를 가지고 있는 서비스(google, facebook 등)
  • Client: 내가 개발한 어플리케이션 및 서비스

목표

facebook으로 로그인하기를 이용하여 내 계정에 대한 정보 받아보기
(= facebook에서 사용자의 access token 발급 받기)

진행 과정

  1. 페이스북 앱 생성 및 설정
  2. 테스트를 위한 웹 서버 올리기
  3. ‘facebook 로그인하기’를 제공할 페이지 작성
    • 사용자(나)에게 권한 요청 후 승인
    • facebook에서 내 정보 요청해서 출력하기

참고

https://github.com/Delf-Lee/OAuth-tutorial

1. 페이스북 앱 생성 및 설정

  • facebook에 앱을 생성합니다.
  • Client ID, Client Secret을 발급 받습니다.(facebook에서는 앱 ID, 앱 시크릿 코드)
  • Redirection URI를 설정합니다.

절차

  1. Facebook for developer 가입 및 로그인
  2. [내 앱] - [새 앱 만들기]
    • 표시 이름, 이메일 기입
    • [앱 만들기]
  3. [제품 추가] - [Facebook 로그인] - 설정
    • [웹] 선택
    • 서비스 제공할 URL 입력 - [Save]
  4. [facebook 로그인] - [설정] - 유효한 OAuth 리디렉션 URI

Redirection URI는 Client에서 facebook 로그인 기능을 제공할 페이지의 URI입니다.

2. 웹 서버 올리기

어떤 웹 서버든 상관 없지만, 이 과정에서는 간단하게 nodejs에서 제공하는 loacl-web-server를 사용하겠습니다.

  • npm: local-web-server
  • 설치: npm install -g local-web-server
  • 실행: ws --https - https

3. facebook 로그인하기를 제공할 페이지 작성

  • 방법 1. URL을 이용한 직접 요청
  • 방법 2. Javascript SDK를 이용한 요쳥

    방법 1. URL을 이용한 직접 요청

  • 목표
    • ‘권한승인 바로가기’를 누르면 facebook 권한설정 페이지으로 이동
    • 승인 완료 후, facebook에서 내 정보를 가져와서 이름 출력
    • 개발자 도구로 응답 메시지 확인
      <!doctype html>
      <html>
      <body>
      <div id="notice">
      이 기능을 이용하기 위해서는 facebook에서 권한을 승인해야 합니다.
      <!-- Resouce Owner가 Resouce Server에게 요청할 URL-->
      <a href="https://www.facebook.com/v3.2/dialog/oauth?
      client_id={app-id}
      &redirect_uri={redirect-uri}
      &state={state-param}
      &scope=email">
      권한승인 바로가기</a>
      </div>
      <div id="welcome" style="display:none"></div>

      <!-- 송수신 확인을 위한 스크립트 -->
      <script>
      var atr = location.href.match('access_token=([^&]*)'); // 문자열 파싱
      console.log('access token regular expression : ', atr);
      if (atr) {
      var access_token = atr[1]; // 토큰 추출
      console.log('access token : ', access_token);
      fetch(
      "https://graph.facebook.com/v3.2"
      + "/me"
      + "/?access_token=" + access_token
      + "&fields=name, email" // 이름과 이메일 요청
      )
      .then(function (raw) {
      return raw.json();
      })
      .then(function (result) {
      if (result.error) {
      } else {
      console.log(result);
      document.querySelector('#notice').style.display = 'none';
      document.querySelector('#welcome').style.display = 'block';
      document.querySelector('#welcome').innerHTML = "Welcome, " + result.name;
      }
      })
      }
      </script>
      </body>
      </html>

리디렉션 할 URL과 필수 매개변수

  • 참고: facebook-로그인 플로 직접 빌드

    https://www.facebook.com/v3.2/dialog/oauth?
    client_id={app-id}
    &redirect_uri={redirect-uri}
    &state={state-param}
  • app-id
    앱의 대시보드에 있는 앱 ID입니다.

  • redirect_uri
    사용자가 다시 로그인하도록 리디렉션할 URL입니다. facebook 앱에서 등록된 유효한 OAuth 리디렉션 URI이어야 합니다. 지금은 현재 페이지로 설정해줍니다. (ex> https://localhost:8000/OAuth-tutorial)
  • state:
    요청과 콜백 간에 상태를 관리하기 위해 앱에서 생성하는 문자열 값입니다. 이 매개변수는 사이트 간 요청 위조를 차단하는 데 사용되어야 하며, 리디렉션 URI에서 변경되지 않은 상태로 개발자에게 다시 전달됩니다.

매개변수 scope

필수는 아니지만, Client가 Resource Server에서 접근수 있는 Resource owner의 정보의 범위를 표기합니다. 예제에선 1234라는 임시 값을 넣어주었습니다.

결과

  • 권한 바로가기를 누릅니다.
  • 이미 권한이 있다면, 로그인 화면은 나타나지 않습니다.
  • 권한 승인 후 URL이 변경된 것을 확인할 수 있습니다. 이렇게 전달 받은 값(access token)으로 사용자의 정보에 접근할 때 이용할 수 있습니다.
    https://localhost:8000/oauth-test/fb-low.html
    #state=1234++++++++
    &access_token=EAADlUGrSbD4BALDg1675ypt9ZAbCI8axbVv1d3H0Du963ntL5q7AkRwrrR3GWhOAZB2NsUZAdUq5JPUZAP08Tmu8yjTvnB3bTYOvwwIJjYzO4xU7Sd71a2mSxlqR2TZBxCsfGJJZCzcftK8htv6edsO5mXOKhYcZCDYIwZC8sy2sLRtZAqMZAgZBJoxn1p2ZA7HMZB74ZD&expires_in=7168
    &reauthorize_required_in=7776000
    &data_access_expiration_time=1549695632

방법 2. Javascript SDK를 이용한 요쳥

참고

  • 결과
    • 로그인이 안되었다면 로그인 버튼 띄우기
    • 로그인이 되었지만, 권한 승인이 안되있으면 facebook 권한설정 페이지로 이동
    • 로그인이 되었고, 권한 승인도 되어있으면 이름과 로그아웃 버튼 띄우기
  • 구현
  • FB.getLoginStatus()를 통해 로그인 여부를 확인합니다.
    • response 값에 access token값이 포함되어 있습니다.
  • 로그인 여부에 따라 FB.login()를 이용하여 로그인을 유도합니다.
    <!doctype html>
    <html>

    <body>
    <div id="welcome"></div>
    <div id="notice">
    <input type="button" id="authBtn" value="checking..." onclick="
    if(this.value === 'Login'){
    FB.login(function(response){
    refreshAuthStatus();
    }, {scope:'email'}); // scope 설정 가능
    } else {
    FB.logout(function(response){
    refreshAuthStatus();
    });
    }
    ">
    </div>
    <script>
    function refreshAuthStatus() {
    FB.getLoginStatus(function (response) {
    console.log('FB.getLoginStatus', response);
    if (response.status === 'connected') {
    FB.api('/me', function (response) { // me, 혹은 사용자 id 입력
    document.querySelector('#authBtn').value = 'Logout';
    document.querySelector('#welcome').innerHTML = 'Welcome, ' + response.name;
    })
    } else {
    document.querySelector('#authBtn').value = 'Login';
    document.querySelector('#welcome').innerHTML = '';
    }
    });
    }

    window.fbAsyncInit = function () {
    FB.init({
    appId: '{app-id}', // app-id 입력하기
    autoLogAppEvents: true,
    xfbml: true,
    version: 'v3.2'
    });

    console.log('Init');
    refreshAuthStatus();

    };

    (function (d, s, id) {
    var js, fjs = d.getElementsByTagName(s)[0];
    if (d.getElementById(id)) {
    return;
    }
    js = d.createElement(s);
    js.id = id;
    // js.src = "https://connect.facebook.net/ko_KR/sdk.js";
    js.src = "https://connect.facebook.net/en_US/sdk.js";
    fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));
    </script>
    </body>

    </html>

결과

  • 로그인하기 전 authResponsestatus값이 not_authorized인 것을 확인할 수 있습니다.

  • 마찬가지로 권한 승인이 되어 있다면 이 화면은 나타나지 않습니다.

  • 방법 1에서 URL로 받았던 access token값이 이번엔 authResponse에 포함되어 있는 것을 확인할 수 있습니다.

기타

facebook에서 권한 해제를 하고싶다면, [설정] - [앱 및 웹 사이트]에서 해당하는 앱을 삭제합니다.