* 최근 SNS와 웹사이트를 연동하는 일들이 많아지면서, 많은 사이트들이 페이스북 로그인과 연동을 하고 있다. 페이스북에서 어떻게 로그인 연동을 해야 하는지 한번 알아보자.
* 자바스크립트 SDK를 이용한 페이스북 로그인
: 페이스북 앱들은 동작하는 장비나 프로젝트에 따라서 몇 가지의 로그인 단계를 거치게 된다. 이번에는 웹앱에서 로그인하는 단계를 한단계씩 알아볼 것이다. 여기서는 웹사이트인 경우 페이스북에서 추천하는 로그인 방식인 페이스북에서 제공하는 자바스크립트 SDK를 사용해서 페이스북 로그인을 할 것이다. 만약 자바스크립트 SDK를 사용하지 못하는 상황이라면 페이스북에서 제공하는 별도의 로그인 절차를 수동적으로 생성해야 할 것이다.
* 빠른 시작
: 일단 먼저 어떻게 구현해야 하는지 빠르게 훑어본 다음 하나씩 천천히 세부적으로 살펴볼 것이다. 이는 페이스북 로그인을 기존의 시스템에 있는 로그인과 연동하여 구현하고자 할 때 도움이 될 것이다. 그 전에 페이스북 로그인에서는 아주 적은 양의 코드로 로그인 구현이 가능하다는 것을 보여주고자 한다.
: 먼저 SDK를 사용하기 전에 페이스북 앱ID가 필요하다. 이것은 페이스북의 앱 대쉬보드에서 신청이 가능하다.
https://developers.facebook.com/apps/
: 만약 앱이 없다면 위의 사이트에서 신규로 가입하고, 전화를 인증 받은 다음 앱을 생성하면 된다.
: 아래의 소스 코드는 자바스크립트 SDK를 HTML 페이지에서 초기화하는 방법이다.이 때에 위에서 신청하여 나온 앱의 ID를 쓰면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
<!DOCTYPE html> < html > < head > < title >Facebook Login JavaScript Example</ title > < meta charset = "UTF-8" > </ head > < body > < script > // This is called with the results from from FB.getLoginStatus(). function statusChangeCallback(response) { console.log('statusChangeCallback'); console.log(response); // response 객체는 현재 로그인 상태를 나타내는 정보를 보여준다. // 앱에서 현재의 로그인 상태에 따라 동작하면 된다. // FB.getLoginStatus().의 레퍼런스에서 더 자세한 내용이 참조 가능하다. if (response.status === 'connected') { // 페이스북을 통해서 로그인이 되어있다. testAPI(); } else if (response.status === 'not_authorized') { // 페이스북에는 로그인 했으나, 앱에는 로그인이 되어있지 않다. document.getElementById('status').innerHTML = 'Please log ' + 'into this app.'; } else { // 페이스북에 로그인이 되어있지 않다. 따라서, 앱에 로그인이 되어있는지 여부가 불확실하다. document.getElementById('status').innerHTML = 'Please log ' + 'into Facebook.'; } } // 이 함수는 누군가가 로그인 버튼에 대한 처리가 끝났을 때 호출된다. // onlogin 핸들러를 아래와 같이 첨부하면 된다. function checkLoginState() { FB.getLoginStatus(function(response) { statusChangeCallback(response); }); } window.fbAsyncInit = function() { FB.init({ appId : '{앱 ID}', cookie : true, // 쿠키가 세션을 참조할 수 있도록 허용 xfbml : true, // 소셜 플러그인이 있으면 처리 version : 'v2.1' // 버전 2.1 사용 }); // 자바스크립트 SDK를 초기화 했으니, FB.getLoginStatus()를 호출한다. //.이 함수는 이 페이지의 사용자가 현재 로그인 되어있는 상태 3가지 중 하나를 콜백에 리턴한다. // 그 3가지 상태는 아래와 같다. // 1. 앱과 페이스북에 로그인 되어있다. ('connected') // 2. 페이스북에 로그인되어있으나, 앱에는 로그인이 되어있지 않다. ('not_authorized') // 3. 페이스북에 로그인이 되어있지 않아서 앱에 로그인이 되었는지 불확실하다. // // 위에서 구현한 콜백 함수는 이 3가지를 다루도록 되어있다. FB.getLoginStatus(function(response) { statusChangeCallback(response); }); }; // SDK를 비동기적으로 호출 (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 = "//connect.facebook.net/en_US/sdk.js"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk')); // 로그인이 성공한 다음에는 간단한 그래프API를 호출한다. // 이 호출은 statusChangeCallback()에서 이루어진다. function testAPI() { console.log('Welcome! Fetching your information.... '); FB.api('/me', function(response) { console.log('Successful login for: ' + response.name); document.getElementById('status').innerHTML = 'Thanks for logging in, ' + response.name + '!'; }); } </ script > <!-- 아래는 소셜 플러그인으로 로그인 버튼을 넣는다. 이 버튼은 자바스크립트 SDK에 그래픽 기반의 로그인 버튼을 넣어서 클릭시 FB.login() 함수를 실행하게 된다. --> < fb:login-button scope = "public_profile,email" onlogin = "checkLoginState();" > </ fb:login-button > < div id = "status" > </ div > </ body > </ html > |
: 사용하는 웹페이지에 위의 HTML을 올려서 테스트를 해보면 된다. 브라우져의 자바스크립트 개발자 도구를 열어서 확인해보면 testAPI()에서 이름을 콘솔에 뿌려주고 있는 것을 확인할 수 있다. 이렇게 구현한 것이 바로 자바스크립트의 기본적인 로그인 페이지를 마친 것이다. 이것을 기반으로 페이스북 로그인과 연동하는 웹 페이지를 개발하여도 좋지만, 기본 동작을 이해한 다음 활용하는 것이 좋을 것이다.
* 자바스크립트 SDK를 활용한 페이스 로그인 단계
: 웹사이트/웹앱에서 페이스북 로그인을 사용하고 통합하기 위해서는 몇개의 단계를 거쳐야 할 것이다. 위의 예에서 거의 다 확인할 수 있지만, 간략하게 이야기한다면 아래와 같다.
1. 로그인 상태 체크하기: 이미 앱에 로그인이 되어있는지 확인하고, 이 사람이 이전에도 앱에 로그인했었는지 체크한다.
2. 로그인이 되어있지 않다면, 로그인 다이얼로그를 띄우고 데이터 권한을 요청한다.
3. 사용자 인증하기
4. 결과의 access token을 저장하기
5. API 호출하여 사용하기
6. 로그아웃
* 로그인 상태 체크하기
: 첫번째 단계는 웹페이지를 로드할 때 이미 페이스북과 개발한 앱에 로그인했는지 확인해야 한다. 먼저 FB.getLoginStatus 함수를 호출하여 확인할 수 있다. 이 때에 인자로 콜백함수를 받으며, 콜백함수로 현재 접속 상태를 리턴하여 준다. 위의 소스에서 아래의 부분은 바로 페이지의 로드 중에 로그인 여부를 확인하는 부분이다.
1
2
3
|
FB.getLoginStatus( function (response) { statusChangeCallback(response); }); |
: response 객체는 아래와 같은 내용을 담고 있다.
1
2
3
4
5
6
7
8
9
|
{ status: 'connected' , authResponse: { accessToken: '...' , expiresIn: '...' , signedRequest: '...' , userID: '...' } } |
: 위의 status는 현재 사용자의 로그인 상태를 나타내고 있고, 해당 상태는 아래 중 하나가 될 것이다.
– connected: 현재 사용자가 페이스북과 앱에 함께 로그인 되어있다.
– not_authorized: 사용자가 페이스북에는 로그인 되어있으나, 앱에는 로그인되어 있지 않다.
– unknown: 사용자가 페이스북에 로그인되어있지 않다.
: authResponse는 상태가 connected인 경우 추가로 로그인 정보들을 보여준다. 각 속성은 다음의 내용을 담고 있다.
– accessToken: 사용자가 앱에 접근하는 access token
– expiresIn: UNIX 시간으로 토큰이 만기 되어 재생성이 필요한 시기
– signedRequest: 앱을 사용하는 사용자에 대한 서명된 파라미터 정보
– userID: 앱을 사용하는 사용자의 ID
: 앱에서 일단 사용자의 로그인 상태를 알게 된다면 아래의 동작들을 취할 수 있다.
– 만약 사용자가 페이스북에 로그인되어있다면, 로그인 UX/UI로 사용자를 redirect
– 만약 사용자가 앱이나 페이스북에 로그인되어있지 않다면, FB.login()으로 로그인 다이얼로그를 보여주거나 로그인 버튼을 보여주면 된다.
* 로그인 하기
: 만약 사용자가 앱에 로그인 안 했거나, 페이스북에 로그인을 안 했다면, 로그인 다이얼로그를 띄워서 양쪽에 로그인할 수 있도록 해줄 수 있다. 만약 페이스북에 로그인이 안 되어있다면, 먼저 페이스북에 로그인을 시도한 다음 앱에 로그인을 시도할 것이다. 자바스크립트 SDK에서는 이러한 단계를 자동으로 체크하여 진행을 하니, 개발자가 추가적으로 해야 할 일은 없다.
: 누군가를 로그인 시킬 수 있는 방법은 크게 2가지가 있다.
– 로그인 버튼을 사용하기
– 자바스크립트 SDK를 사용하여 FB.login() 사용하기
* 로그인 버튼 사용하기
: 로그인 버튼을 사용하는 방법은 아주 간단하다. 페이스북 로그인 버튼을 사용하는 것에 대한 문서 아래의 사이트에서 찾을 수 있다.
https://developers.facebook.com/docs/plugins/login-button
: 위의 사이트에서 나타내고 싶은 버튼의 종류를 설정한 다음 Get Code를 누르면 소스코드를 직접 가져올 수 있다. 위의 예에서는 로그인 버튼을 사용할 때 성공적으로 로그인했는지 확인하기 위한 콜백함수를 onlogin 속성으로 사용하는 것을 확인할 수 있다.
1
2
|
< fb:login-button scope = "public_profile,email" onlogin = "checkLoginState();" > </ fb:login-button > |
: 위에서 사용한 예제에서 콜백함수 안에서는 FB.getLoginStatus() 함수를 호출하여 로그인 상태를 확인하게 된다.
1
2
3
4
5
|
function checkLoginState() { FB.getLoginStatus( function (response) { statusChangeCallback(response); }); } |
* 자바스크립트 SDK로 로그인 다이얼로그 띄우기
: 웹에서 자기의 버튼을 하고 싶은 경우에는 자바스크립트 SDK의 FB.login()을 사용하여 간단하게 페이스북 로그인 다이얼로그를 띄울 수 있다.
1
2
3
|
FB.login( function (response){ // response 객체를 처리하면 된다. }); |
: 이 함수는 로그인을 하는 팝업 다이얼로그는 띄우게 되므로 사용자가 html button을 눌렀을 때에만 호출되어야 한다. 이렇게 해야 팝업 차단이 안되고 팝업을 띄울 수 있게 되는 것이다.
: FB.login() 함수는 콜백 함수 이외에 추가적인 scope 파라미터를 페이스북에 전달할 수 있는데, 앱에서 사용할 권한의 목록을 콤마(,)로 구분하여 전송하게 된다. 아래는 FB.login()의 이메일 주소와 친구의 목록에 접근하는 권한 함께 요청하게 된다.
1
2
3
|
FB.login( function (response) { // response 처리 }, {scope: 'public_profile,email' }); |
* 로그인 다이얼로그의 결과 다루기
: 이 때에 사용자가 로그인 처리 또는 취소를 하거나, 자기의 정보에 접근하는 것을 허용 또는 취소를 할 수 있을 것이다. 어떠한 선택을 하게 되면, 브라우져에서는 취소 했든지, 로그인에 성공 했든지 일단 웹으로 돌아가게 된다. 이 때에 FB.login()의 함수의 인자로 넘겨준 콜백 함수에 repsonse 객체를 넘겨주게 된다. response는 아래와 같이 처리가 가능하다.
1
2
3
4
5
6
7
8
9
|
FB.login( function (response) { if (response.status === 'connected' ) { // 페이스북과 앱에 같이 로그인되어 있다. } else if (response.status === 'not_authorized' ) { // 페이스북에는 로그인 되어있으나, 앱에는 로그인 되어있지 않다. } else { // 페이스북에 로그인이 되어있지 않아서, 앱에 로그인 되어있는지 불명확하다. } }); |
* 권한 요청하기
: 로그인 다이얼로그를 띄울 때에 중요한 것은 앱에서 어느 데이터를 사용하고자 하느냐이다. 위의 예에서는 scope 파라미터를 사용하는데, 이렇게 요청하는 내용들을 접근 권한이라고 한다. 접근 권한은 별도의 문서에서 더 상세하게 확인이 가능한데, 몇 가지 중요하게 요약을 한다면 아래와 같다.
– 다이얼로그를 생성할 때 권한을 요청한다. 이렇게 해야 리턴되는 access token에 해당 권한을 부여하게 되는 것이다.
– 서로 다른 플랫폼들은 서로 다른 권한이 부여 가능하다. 예를 들면, iOS에서는 사용자가 태그된 위치들이 요청 가능하다면, 웹버전에서는 그렇게 확인이 하지 않아도 될 것이다.
– 더 추가적인 기능이 필요하다면 추가 권한 요청이 가능하다. 새로 추가적인 권한이 필요하다면, 간단하게 권한의 목록 뒤에 하나 추가로 더한 다음에 로그인 다이얼로그를 다시 띄우면 된다.
– 로그인 다이얼로그에서는 사용자에게 어떠한 권한을 요청하고 있는지 명시하게 되어있으며, 이를 거절할수도 있게 되어있다.
– 기본적인 권한 중에서 public_profile, email, 그리고 user_friends 이외에 추가적인 권한은 반드시 페이스북에 의해 먼저 검토 되어야 사용할 수 있다. 따라서 앞의 3가지 권한 이외에 추가로 요청하려면 아래의 사이트에서 로그인 리뷰를 신청해야 한다.
https://developers.facebook.com/docs/apps/review/login
* Access token 저장하기
: 로그인 과정이 끝나고나면, access token이 생성되는데, 이 access token은 검증된 API를 특정 사용자가 특정 앱에서 호출할 때 함께 전달해야 한다. 페이스북 자바스크립트 SDK는 자동으로 access token을 저장하고 브라우져의 로그인 상태를 관리하므로 access token을 브라우져 자체에 저장하기 위해서 별도의 처리를 할 필요는 없다.
: 하지만, 일반적인 사용 패턴은 access token을 서버로 전송하여 서버에서 대신하여 여러 가지 호출을 하는 것이다. 브라우져에서 access token을 가져오기 위해서는 FB.getLoginStatus()를 통해서 콜백되는 함수의 인자로 들어오는 response 객체로 확인하면 된다.
1
2
3
4
5
|
FB.getLoginStatus( function (response) { if (response.status === 'connected' ) { console.log(response.authResponse.accessToken); } }); |
: token은 다양한 길이를 가지는 암호화된 문자열을 가진다. 또한 기억해야 할 것은 브라우져를 통해서 생성된 access token은 몇 시간 동안만 사용 가능하고, 자바스크립트 SDK를 통해서 자동적으로 갱신 된다. 만약 서버에서 access token을 가지고 지속적으로 APi를 호출하고 싶다면 장기간의 token을 신청해야 한다.
* 사용자 인증하기
: 앱에서는 일반적으로 로그인 다이얼로그의 처리 결과를 받는 사람과 처음 시작한 사람이 같은 사람이라는 것을 검증해야 한다. 만약 브라우져에서만 자바스크립트 SDK를 사용하고 있다면, 이러한 검증은 자동적으로 수행하게 되는 것으로 생각하면 된다.
: 만약 서버에 access token을 받아서 보내고자 한다면, 서버에 도착하고나서 access token을 재인증 해야 한다. 이 때에는 app_id와 user_id가 해당하는 access token과 일치하는지 확인해야 한다.
* API 호출하기
: 이 단계가 되면 사용자가 로그인을 하여 인증이 끝난 상태가 된다. 이제부터는 API를 호출하여 연동을 하면 된다. 브라우져에서 API를 호출하는 가장 쉬운 방법은 바로 FB.api()를 호출하는 것이다. 브라우져에서 FB.api()를 호출하게 되면 access token은 자동적으로 전송하게 된다. 아래는 API 하나의 예이다.
1
2
3
|
FB.api( '/me' , function (response) { console.log(JSON.stringify(response)); }); |
: 위의 API 호출은 아래의 배열을 리턴할 것이다.
1
2
3
4
5
6
|
{ "id" : "101540562372987329832845483" , "email" : "example@example.com" , "first_name" : "Bob" , [ ... ] } |
: 만약 서버쪽에서 access token을 사용하여 API를 호출하고 있다면, 서버에 SDK와 유사하게 호출을 하면 된다. 많은 사람들은 PHP로 구성된 웹앱을 사용하고, 아래의 사이트에서 서버 측 API 호출에 대한 문서를 찾아볼 수 있다.
https://developers.facebook.com/docs/php/gettingstarted/4.0.0
* 로그아웃 하기
: 자바스크립트 SDK를 이용하여 FB.logout을 사용한다면 버튼이라 링크를 통하여 사용자를 로그아웃 시킬 수 있다.
1
2
3
|
FB.logout( function (response) { // 사용자 로그 아웃 이후 콜백처리 }); |
: 이 함수는 사용자를 페이스북에서도 로그아웃을 시키게 된다는 것을 참고하기 바란다. 이것을 참고하는 이유는 어떠한 사람들은 앱에 로그인해 있는 동안 페이스북에도 접속했을 수도 있다. 이 때에 사용자들은 페이스북과 앱에서 동시에 로그아웃하는 것을 예상하고 있지 못할수도 있지만, 사용자의 혼동을 줄이고 보안을 지키기 위하여 이러한 로그아웃 방식을 채택하고 있다.
: 추가적으로 로그아웃은 로그인 권한을 재요청하는 것과는 다르기 때문에, 앱을 개발할 때, 로그아웃한 사용자에게 다시 로그인 다이얼로그를 띄우면서 로그인 요청을 하는 것은 지양해야 한다.
* 권한 추가하기
: 페이스북 로그인의 가장 적합한 구현 예는 바로 읽기 권한과 배포 권한을 동시에 요청하지 않는 것이다. 이를 위해서 페이스북에서는 앱에서 나중에 다른 권한을 추가로 요청할 수 있도록 지원해주고 있다. 이를 위해서는 로그인 다이어리에 새로운 권한을 요청하도록 띄우면 된다. 예를 들면, 아래와 같은 로그인 버튼을 사용했다면, 다이얼로그는 아래와 같을 것이다.
1
2
|
<fb:login-button scope= "public_profile,email" onlogin= "checkLoginState();" > </fb:login-button> |
: 그리고 권한이 부여된 뒤에 /me/permissions API를 호출하게 되면 아래와 같이 권한이 부여된 것을 확인할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
|
{ "data" : [ { "permission" : "public_profile" , "status" : "granted" }, { "permission" : "email" , "status" : "granted" } ] } |
: 만약 여기서 나중에 user_friends 권한을 추가로 요청하고 싶다면, FB.login() 함수를 아래와 같이 다시 호출하면 된다.
1
2
3
|
FB.login( function (response) { console.log(response); }, {scope: 'user_friends' }); |
: 이렇게 호출하는 것 또한 버튼이나 사용자의 클릭 핸들러를 통해서 열어야 브라우져의 팝업 차단기를 피할 수 있다. 이 때에 팝업은 아래와 같이 나타나게 된다.
: 이 때에 새로 추가된 권한에 대해서만 추가적으로 요청하는 것을 확인할 수 있다. 새로운 권한 요청을 사용자가 승낙하고 난 뒤에 다시 /me/permissions API를 요청하게 되면 아래와 같이 결과가 나타난다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
{ "data" : [ { "permission" : "public_profile" , "status" : "granted" }, { "permission" : "email" , "status" : "granted" }, { "permission" : "user_friends" , "status" : "granted" } ] } |
* 거절 당한 권한 재 요청하기
: 페이스북에서는 사용자들이 권한을 거절할 수 있도록 설정하고 있다. 로그인 다이얼로그는 아래와 같은 화면으로 설정할 수 있도록 되어있다.
: public_profile은 항상 기본적으로 요청되기 때문에 설정을 바꿀 수 없도록 되어있고, 바꿀 수 있는 항목들은 설정이 가능하다. 이렇게 설정이 가능한 설정을 바꾸게 되면, /me/permissions API를 호출하게 되면, 거절한 권한에 대하여 아래와 같이 결과가 나타난다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
{ "data" : [ { "permission" : "public_profile" , "status" : "granted" }, { "permission" : "user_likes" , "status" : "declined" } ] } |
: 위에서 보면 user_likes는 declined 된 상태로 확인할 수 있다. 거절된 권한에 대해서 한번은 처리하는 것은 괜찮으나, 추가적으로 거절된 권한을 요청할 때에는 왜 그러한 권한이 필요한지 제대로된 교육 자료를 만들어서 제시하는 것이 좋을 것이다. 하지만, FB.login()을 그냥 다시 요청하게 되는 경우에는 요청이 이루어지지 않을 것이다. 이것은 사용자가 한번 권한을 거절하게 되면 다음 로그인 다이얼로그를 띄우게 되면 명시적으로 다시 요청해달라고 하기 전까지는 사용자에게 다시 묻지 않도록 되어있기 때문이다. 이 때에는 auth_type: rerequest 플래그를 활성화 시켜야 한다.
1
2
3
4
5
6
7
8
9
|
FB.login( function (response) { console.log(response); }, { scope: 'user_likes' , auth_type: 'rerequest' } ); |
: 이렇게 요청을 다시 하게 되면 로그인 다이얼로그에서는 거절되었던 권한에 대하여 다시 요청하게 된다.
* 사람들이 앱을 언인스톨 할 때 감지하기
: 사람들이 앱 자체를 통해서 언인스톨을 하는 것이 아니라 페이스북을 통해서 앱을 언인스톨하는 것이 가능하다. 앱에서 이러한 일이 일어나게 되는 것을 감지하려면, 이러한 이벤트가 일어나게 되면 콜백 URL을 통해서 앱에서도 알 수 있다.
: 언인스톨 콜백은 앱의 대쉬보드를 통해서 설정할 수 있다. 페이스북 앱 페이지로 가서 Settings 메뉴를 선택한 다음, Advanced 탭을 선택하면 텍스트 필드 중에서 Deauthorize Callback URL 에 콜백을 받을 URL을 입력하면 된다.
: 앱에 있는 사용자가 de-authorize하는 경우에 이 URL에 HTTP_POST를 통해서 요청을 보내게 된다. 이 때에 콜백함수에 signed request를 추가로 보내게 되는데, 이를 파싱하는 것은 페이스북의 레퍼런스를 참고하면 된다.
원문 참고: https://developers.facebook.com/docs/facebook-login/login-flow-for-web/v2.1