PHP/PHP

[PHP]페이스북 로그인 API 연동하기(공식 SDK 사용)

테서르 2021. 1. 29. 22:40
반응형
PHP 8.0 이상을 사용하시는 분들은 curl을 사용하셔야 합니다.
8.0은 사용이 가능하지만 최신 SDK를 사용할 수 없고, 8.1부터는 제외된 기능때문에 사용이 불가능합니다.
해당하시는 분들은 https://teserre.tistory.com/21를 참조해 주세요.

 

페이스북이 제공하는 다양한 API를 사용하기 위해서는 기본적으로 페이스북 로그인 API를 사용하여야 한다.

 

Javascript로도 구현이 가능하지만 보안이나 세션 등의 이유로 PHP와 Facebook PHP SDK로 연동하는 방법을 정리를 해 보았다.

 

참고로 필자의 서버 환경은 ubuntu 18.04LTS, Apache를 사용하고 있다.

 

 

※ 연동 전 필수 작업

페이스북 뿐만이 아니라 다른 모든 SNS 로그인 API를 사용하기 위해서는 웹사이트에 https를 적용해야 한다. 보안상의 이유로 https를 적용하지 않으면 로그인 API를 사용할 수 없다. 무료로 쉽게 하는 방법으로는 Let's Encrypt를 사용하는 방법이 있다.

https://teserre.tistory.com/4에 Let's Encrypt를 사용하는 방법을 적어두었다.

 

 

1. 페이스북 앱 만들기

https://developers.facebook.com에 접속하여 로그인을 한 후에 '내 앱'을 눌러 다음 화면으로 넘어간다.

 

 

'Create App' 또는 '앱 만들기' 버튼을 클릭한다.

 

 

 

세 가지 유형이 나오는데 목적에 맞는 것을 선택하면 된다. 페이스북 그래프 API도 사용할 예정이기에 이 글에서는 '비즈니스 통합 관리'를 선택하였다.

 

※ 2021-02-09

최근 다시 확인해보니 페이스북 API 버전이 9.0으로 업데이트 되면서 앱 유형별로 접근 권한이 분리가 되었다. 기존에는 '비즈니스 통합 관리'로 대부분의 권한을 얻을 수 있었지만 9.0부터는 상황별로 앱을 만들어야 한다는 것이다.

 

 

페이스북 페이지를 관리할 목적 - 비즈니스 통합 관리

 

앱 센터, 인스턴트 게임 등 게임과 관련된 SDK가 필요 - 게임 빌드 또는 연결하기

 

로그인한 사용자의 페이스북 정보에 접근 - 연결된 환경 구축

 

이 정도로 요약이 된다. 자세한 사항은 페이스북 공식 문서(https://developers.facebook.com/docs/development/create-an-app/app-dashboard/app-types)를 참조하길 바란다.

 

공통적으로 페이스북 로그인 기능은 사용할 수 있으니 로그인만이 목적이라면 아무거나 선택하여도 상관 없을 듯 하다.

 

 

 

 

유형 선택 후에 앱 이름과 목적을 입력해야 한다. 앱 이름은 웹 사이트 등의 서비스에서 사용자들에게 보이는 이름이다. 이 글에서는 단순한 가이드를 위한 앱을 생성하고 있으므로 간단하게 이름을 입력하였다.

앱 목적도 상황에 따라 선택을 하면 된다. 선택 후 '앱 ID 만들기'를 누르면 로봇인지 확인한 후 앱이 만들어진다.

 

 

 

2. 페이스북 로그인 API 설정

 

페이스북 앱을 생성하였으면 이제 필요한 API를 추가해야 한다.

 

페이스북 앱을 생성하였다면 위 사진과 같은 페이지로 자동으로 이동한다. 여기서 'Facebook 로그인' 구역의 '설정'을 클릭한다.

 

 

 

PHP를 통한 웹 페이지에서의 로그인을 구현하고 있으므로 웹을 선택한다.

 

 

 

앱을 사용할 사이트의 주소를 입력한다. 반드시 https를 사용한 주소를 입력해야 한다. 입력 후 'Save'를 누른다.

 

 

 

 

 

화면 왼쪽의 Facebook 로그인 메뉴의 설정을 눌러 API의 설정을 변경한다.

 

 

 

'유효한 OAuth 리디렉션 URI'에 페이스북 로그인 정보를 처리할 콜백 주소를 입력한다. 이 항목을 입력하지 않고 서비스에 페이스북 앱을 추가하면 'URL을 읽어 들일 수 없음'이라며 에러가 발생한다.

 

콜백 처리는 페이스북 공식 github에서 확인할 수 있다. 또는 아래쪽에 추가된 코드를 사용해도 된다.

입력을 한 후 변경 내용을 저장한다.

 

 

 

아래쪽에 유효성 검사기가 있는데 위의 유효한 리디렉션 URI에 추가된 주소를 입력하여 제대로 적용이 되었는지 확인 할 수 있다.

 

 

3. PHP SDK로 로그인 적용

이제 서비스에 로그인 API를 적용하기 위해 코드를 작성해야 한다. 이를 위해 우선 PHP를 운영하는 서버에 Facebook PHP SDK를 설치한다.

 

composer require facebook/graph-sdk

Facebook PHP SDK는 composer를 사용하여 설치한다. composer를 설치하지 않았다면 우선 composer부터 설치를 한다.

 

SDK를 설치한 후 로그인 리디렉션 주소를 생성하는 코드를 작성한다.

 

SDK를 사용할 때 앱의 id와 시크릿 코드가 필요하다.

 

설정->기본 설정 탭을 누르면 앱 ID와 앱 시크릿 코드를 확인할 수 있다. 두 가지 모두 외부에 노출이 되면 보안 문제가 생길 수 있으므로 절대 외부에 노출해서는 안된다.

 

아래쪽에 '앱 도메인'을 입력하는 칸이 있는데, 여기에 페이스북 앱을 넣을 사이트의 주소를 입력해야 한다. https://example.com/test 의 형식이나 https://example.com/ 과 같은 형식 아무거나 입력해도 된다. 자동으로 https://example.com/ 형식으로 변환이 된다.

 

앱 도메인을 입력하지 않으면 callback 처리 시에 URL을 불러올 수 없다며 에러가 발생한다. 만약 입력을 했는데도 에러가 발생하면 오타가 있는지 확인해 보고, 문제가 없다면 잠시 기다리는 수밖에 없다.

 

※ 2021-02-09 추가

페이스북 api가 8.0에서 9.0으로 업데이트 되면서 '개인정보처리방침 URL'을 반드시 입력하게 되었다. 테스트해보니 그냥 도메인 형식만 맞으면 적용이 되었다. 테스트용이면 상관없지만 추후 서비스로 사용할 경우에는 올바른 URL로 변경해야 한다.

 

 

fblogin.php

<?php

require_once './vendor/autoload.php';

//페이스북 앱 정보 입력
$fb = new Facebook\Facebook([
    'app_id' => 'app_id',	//페이스북 앱 id
    'app_secret' => 'app_secret',	//페이스북 앱 시크릿 코드
    'default_graph_version' => 'v8.0',	//api 버전.
    ]);
    
$helper = $fb->getRedirectLoginHelper();

//사용자정보에 접근할 권한 옵션. 추가 옵션은 공식 문서 참조
$permissions = ['public_profile'];

//로그인 주소 생성. callback 주소 입력
$loginUrl = $helper->getLoginUrl('https://example.com/fb-callback.php', $permissions);

//로그인 버튼 생성
echo '<a href="'.htmlspecialchars($loginUrl). '" class="button-fb-login">Facebook으로 로그인</a>';

?>

페이스북 로그인 페이지로 리디렉션을 해 주는 링크를 생성하는 코드다. $fb 변수에 입력하는 페이스북 앱 id, 앱 시크릿 코드를 정확하게 입력해야 한다. 

그리고 $loginUrl 변수에 콜백을 받을 주소를 입력해야 하는데, 이 주소를 잘못 입력하면 차단된 URL이라며 페이스북 로그인을 할 수 없다. 앱 설정을 할 때 입력한 '유효한 OAuth 리디렉션 URI' 주소를 입력하면 문제없다.

이 화면이 뜬다면 앱 설정의 '유효한 OAuth 리디렉션 URI'주소와 php 코드를 확인

 

코드를 제대로 입력하였는데도 '매개변수에 리디렉션 URI가 없습니다: URI에 리디렉션이 없습니다'라는 에러가 뜰 경우는 php에서 생성된 url에 문제가 있다는 것이다.

 

html에 출력을 할 때 정상적으로 출력을 하기 위해 htmlspecialchars() 함수를 사용하였는데 이 함수가 올바른 주소를 변형시켜서 생긴 문제인 것이다.

 

htmlspecialchars($loginUrl) 부분을 $loginUrl로 바꾸면 문제가 해결된다.

 

fb-callback.php

<?php

require_once './vendor/autoload.php';

if(!session_id()) {
    session_start();
}

$fb = new Facebook\Facebook([
    'app_id' => 'app_id',
    'app_secret' => 'app_secret',
    'default_graph_version' => 'v8.0',
    ]);

$helper = $fb->getRedirectLoginHelper();

//state 에러가 발생하는 경우 추가
if (isset($_GET['state'])) {
    $helper->getPersistentDataHandler()->set('state', $_GET['state']);
}

// 사용자 액세스 토큰 획득
try {
    $accessToken = $helper->getAccessToken();
} catch(Facebook\Exceptions\FacebookResponseException $e) {
    echo 'Graph returned an error: ' . $e->getMessage();
    exit;
} catch(Facebook\Exceptions\FacebookSDKException $e) {
    echo 'Facebook SDK returned an erro: '.$e->getMessage();
    exit;
}

//각종 에러 처리
if(!isset($accessToken)) {
    if($helper->getError()) {
        header('HTTP/1.1 401 Unauthorized');
        echo "Error: " . $helper->getError()."\n";
        echo "Error Code: " . $helper->getErrorCode()."\n";
        echo "Error Reason: " . $helper->getErrorReason()."\n";
        echo "Error Description: " . $helper->getErrorDescription()."\n";
    } else {
        header('HTTP/1.1 400 Bad Request');
        echo 'Bad request';
    }
    exit;
}


//사용자 액세스토큰 출력
echo '<h3>Access Token</h3>';
var_dump($accessToken->getValue());

$oAuth2Client = $fb->getOAuth2Client();

$tokenMetadata = $oAuth2Client->debugToken($accessToken);

//사용자 토큰 정보 출력
echo '<h3>Metadata</h3>';
var_dump($tokenMetadata);

$tokenMetadata->validateAppId('{app_id}');

$tokenMetadata->validateExpiration();

//장기 토큰 변환
if(!$accessToken->isLongLived()) {
    try{
        $accessToken = $oAuth2Client->getLongLivedAccessToken($accessToken);
        $response = $fb->get('/me', $accessToken);
    } catch(Facebook\Exceptions\FacebookSDKException $e) {
        echo "<p>Error getting long-lived access token: " . $e->getMessage()."</p>\n\n";
        exit;
    }
    $graphNode = $response->getGraphNode();
}

//변환된 장기 토큰 출력
echo '<h3>Long-lived</h3>';
var_dump($accessToken->getValue());

//액세스 토큰 세션에 저장
$_SESSION['fb_access_token'] = (string) $accessToken;

?>

페이스북 로그인 정보를 받아와서 사용자 액세스 토큰을 획득한 후 장기 토큰으로 변환까지 실행하는 코드이다.

페이스북 문서에 따르면 로그인 시 획득하는 액세스 토큰은 1~2시간 정도의 수명을 가지고 있다. 따라서 DB에 저장하여 오랜 기간 동안 사용을 할 수 없다. 필요할 때마다 페이스북에 로그인을 요구해 토큰을 재발급 받아야 한다는 것이다.

 

다행히도 단기 토큰을 장기 토큰으로 변환 할 수 있다. 문서에는 약 60일 정도의 수명을 가지고 있다고 한다. 그러나 모종의 이유로 조기 만료가 되는 경우도 있다고 한다. 이럴 때는 액세스 토큰이 만기 되었는지 체크를 하고 새로 발급받는 수밖에 없다.

 

 

4. 테스트

fblogin.php를 실행하면 페이스북 로그인 주소가 링크가 되어있다. 이를 클릭하면 로그인 화면으로 리디렉션 된다.

 

앱에서 접근할 권한을 검토하는 화면이 나온다. '제공할 정보 검토'를 눌러 요구하는 권한이 제대로 적용되어 있는지 확인하고 계속 버튼을 눌러 다음으로 진행한다.

 

 

 

fb-callback.php 페이지에서 사용자의 액세스토큰과 페이스북 앱에 대한 정보가 출력된다. 이 화면이 나오면 페이스북 계정과 페이스북 앱에 연동이 성공한 것이다. 로그인한 페이스북 계정으로 들어가면 앱에 로그인했다는 알림이 있을 것이다.

 

액세스 토큰의 길이는 가변적이여서 언제나 같은 길이로 발급되지 않는다. 짧아질 수도, 길어질 수도 있는 것이다. 그래서 DB에 저장할 경우 조금 넉넉하게 잡는 것이 좋다.

 

이 코드는 단순히 액세스 코드를 획득하는 동작만 한다. PHP SDK를 활용하여 다른 정보를 얻는 방법에 대해서는 다른 페이지에서 자세히 설명할 예정이다.

 

 

 

 

※ 추가사항

1. 개발중인 앱으로는 아무 계정으로 로그인을 할 수 없다. 앱을 라이브 상태로 변경한 후에 로그인이 가능하다. 앱의 상태를 라이브로 변경하기 위해서는 개인정보처리방침 등 추가적으로 입력할 것들이 있다. 자세한 사항은 공식 문서를 참조하면 된다.

 

2. 페이스북 앱을 제대로 사용하기 위해서는 반드시 페이스북에 앱 검수를 요청해야 한다. 그런데 현재 코로나로 인해 개인 인증은 막힌 상태이다. 즉, 혼자서 개발하는 사람은 페이스북 앱의 기능을 사용할 수 없다는 뜻이다. 비즈니스 인증을 통한 검수만이 열려있는데, 기업명과 사업자번호 등 기업임을 인증해야 하는 과정이 포함되어 있다.

반응형

'PHP > PHP' 카테고리의 다른 글

[PHP]페이스북 로그인 연동하기(curl 사용)  (0) 2022.02.23
[PHP] php 세션(Session) 사용하기  (4) 2021.02.22