페이스북(Facebook) 계정으로 로그인하는 C# 웹 사이트 제작
트위터 계정 연동을 알아보았는데요.
트위터 계정으로 로그인하는 C# 웹 사이트 제작
; https://www.sysnet.pe.kr/2/0/948
기왕 하는 거 ^^ 페이스북도 알아봐야 하지 않을까요?
어차피 모두 OAuth 인증 방식을 도입했기 때문에 접근 방법도 비슷해서 부담이 적습니다.
지난 번처럼, 우선 .NET 용 라이브러리를 찾아야 할텐데요. 오픈 소스로 되어 있는 다음의 라이브러리가 Facebook에 의해서 링크되어 있습니다.
C# SDK for Facebook Platform
; https://github.com/facebook/csharp-sdk
소스 코드로만 공개되어 있기 때문에 번거롭지만 다운로드 받아서 빌드를 직접 해줘야 합니다. (FacebookAPI.dll)
그다음, 트위터와 마찬가지로 페이스북 역시 여러분들의 응용 프로그램을 등록해 줘야 합니다. 검색을 해보니, 아래의 사이트에서 잘 설명을 해주고 있습니다. ^^
SNS - 페이스북에 어플리케이션 올리기
; http://sherlockpj.blog.me/70091818802
위에서 일러준데로,
http://www.facebook.com/developers 링크로 이동해서 로그인을 하고, 아래의 허가 요청에 대해서 허용을 합니다. (특이하게도, 페이스북 내부의 개발자 설정 역시도 페이스북의 '외부 응용 프로그램'처럼 대우를 하는군요.)
다음으로, "새 어플리케이션 설정" 버튼을 누르고,
응용 프로그램 이름을 입력하고, 생성!
이후의 과정은 각자 응용 프로그램 상황에 맞게 설정하고 확인을 누르면 완료.
트위터의 경우에 "Consumer Key"와 "CustomerSecret"를 얻을 수 있었던 것처럼, 페이스북에서도 비슷한 값들을 "Application ID"와 "Application Secret"으로 제공하고 있습니다.
하지만, 인증 서비스에 있어 페이스북이 좀 더 다양한 기능들을 제공해 주고 있는데요. 개인적으로 마음에 드는 것이 SSO(Single-Sign-on) 기능과 "Deauthorize URL" 등록 기능입니다.
우선, ASP.NET에서의 SSO 구현은 다음의 웹 사이트에서 자세히 설명하고 있습니다.
Facebook Platform's OAuth 2.0 Protocol and ASP.NET MVC
; http://amirrajan.net/Blog/asp-mvc-and-facebook-single-sign-on
위와 같이 서버 측에서 제어하는 것도 가능한데요. 페이스북은 클라이언트의 JavaScript에서도 SSO 인증이 되도록 하는 js 파일을 공개해 주고 있습니다. 이에 대해서는 다음의 글에서 "Single Sign-on" 부분을 참고하실 수 있습니다.
Facebook for Websites
- Single Sign-on
; http://developers.facebook.com/docs/guides/web
위의 글에서 설명된 것처럼 SSO 구현은 여러분들의 웹 사이트에 다음과 같은 HTML 및 Javascript 링크와 코드를 추가해 주는 것으로 간단하게 적용될 수 있습니다.
<div id="fb-root"></div>
<script src="http://connect.facebook.net/en_US/all.js"></script>
<script>
FB.init({appId: '[응용 프로그램 등록 시 받는 Application ID]', status: true, cookie: true, xfbml: true});
FB.Event.subscribe('auth.sessionChange', function(response) {
if (response.session)
{
// 로그인 상태로 판정될 때 실행되는 코드
} else {
// 로그아웃 상태로 판정될 때 실행되는 코드
}
});
</script>
<fb:login-button></fb:login-button> <!-- 로그인 버튼 이미지 -->
<fb:login-button />으로 표시되는 로그인 버튼 이미지를 사용자가 클릭하면 페이스북 측에서 제공하는 로그인 화면이 팝업창으로 뜨고 사용자는 페이스북 로그인 하듯이 사용자 정보를 입력합니다. 물론, 웹 사이트 측에는 트위터에서 그랬던 것처럼 사용자 계정에 대해서는 어떠한 정보도 알려주지 않고 access_token 값 만을 넘겨주게 됩니다.
FB.init / FB.Event.subscribe의 자바스크립트 역할은 간단합니다. 만약, 사용자가 Facebook 로그인에 대해서 "로그인 상태 유지(Remember Me)"를 체크해 놓고 로그인 한 적이 있다면, 위의 자바 스크립트 함수를 포함하는 웹 사이트를 방문하면 초기 FB... 메서드 실행 시에 페이스북 사이트로부터 정보를 조회해서 로그인 처리를 하게 됩니다. 반대로, 현재 로그인 해서 사용하고 있는 웹 사이트와는 별개의 창으로 떠 있는 웹 브라우저에서 방문중인 페이스북에서 로그아웃을 하는 경우에도, 위의 자바스크립트가 실행되면 '로그 아웃' 부분에 해당하는 자바 스크립트 코드가 실행될 수 있습니다.
인증처리를 서버측에서 하느냐, 자바스크립트로 하느냐에 대해서는 장단점이 있습니다. 자바스크립트를 활용하게 되면 서버 측에서 지저분하게 인증 관련 코드를 넣을 필요가 없어서 좋긴 하지만 대부분의 경우 다시 화면을 refresh 해주는 코드를 자바스크립트에 넣어주어서 화면 깜빡임이 발생하게 됩니다.
SSO를 조금이라도 아시는 분들이라면, 그 방법이 쿠키임을 짐작하실 테고, 그렇다면 쿠키가 적용되는 도메인 영역이 지정되어야 할 텐데, 페이스북은 어떻게 이를 판단할까요? 네... 이 부분은 응용 프로그램 등록화면에서 쿠키가 적용될 도메인 영역을 다음과 같이 미리 지정해 주었어야 합니다.
로그인 된 경우, 지정된 도메인 영역으로 다음과 같은 쿠키 설정이 추가됩니다.
fbs_[AppId]="access_token=[AppId]...&base_domain=[사이트 도메인]&expires=...[인증유효기간]...&secret=....&session_key=....&sig=....&uid=...";
페이스북 로그인 연동이 적용된 제 웹 사이트의 경우에 풀어보면 다음과 같습니다.
fbs_[AppId]="...[이하 아래의 값들이 개행문자 없이 나열됨]..."
access_token: ...[생략]...
base_domain: www.sysnet.pe.kr
expires: 1290085200
secret: ...[생략]...
session_key: ...[생략]...
sig: ...[생략]...
uid: ...[생략]...
name : SeongTae Jeong
email: ...[생략]...
website: https://www.sysnet.pe.kr
위의 정보에서 중요한 것은 "access_token" 값입니다. 그 값을 기반으로 이전에 빌드해 둔, FacebookAPI.dll을 이용하여 페이스북 웹 사이트로부터 제공되는 다양한 API를 접근하게 되는데, 이와 관련해서 자세한 개발 관련 정보는 아래의 웹 페이지에서 찾아볼 수 있습니다.
Graph API Overview
; http://developers.facebook.com/docs/api
Graph API Reference
; http://developers.facebook.com/docs/reference/api/
예를 들어, "사용자" 정보를 조회하고 싶다면, "Graph API Reference"에서 살펴보고
http://developers.facebook.com/docs/reference/api/user에서 설명되고 있는 것임을 인식하고, 그 페이지에 제시된 쿼리 URL을 아래와 같이 찾을 수 있습니다.
User
A user profile. This object supports Real-Time Updates for all properties except the verified property.
예
https://graph.facebook.com/me (current user)
도메인 까지의 쿼리 주소는 FacebookAPI에서 붙여주기 때문에 뒤의 "/me"만 붙여서 다음과 같이 조회를 해 올 수 있습니다.
Facebook.FacebookAPI api = new Facebook.FacebookAPI(...[쿠키에서 구해온 access_token 값]...);
Facebook.JSONObject me = api.Get("/me");
그런 후, 반환되는 것은 해당 명세서에 보이는 것 처럼 id, first_name,... 등등의 값을 다음과 같이 조회해 올 수 있습니다.
string userName = me.Dictionary["first_name"].String;
string userId = me.Dictionary["id"].String;
여기까지 기본적인 인증 방법 및 사용법 설명은 끝입니다.
부가적으로, 더 설명드려야 하는 것이 있다면 "사용자 정보" 조회 등에 대해서 일부 정보는 반드시 사용자로부터의 허락을 받아야만 가져올 수 있다는 점입니다. (이 부분에 대해서는 페이스북 개발자에게 정말 박수를 쳐주고 싶습니다. ^^)
예를 들면, 위의 api.Get("/me"); 코드를 통해서 사용자 정보를 조회할 때 email을 조회하면 빈 문자열이 반환되는 것을 확인할 수 있습니다. 왜냐하면, email 정보는 "사용자"가 해당 응용 프로그램이 조회해도 좋다는 허락을 해줘야 하기 때문입니다.
이에 대해서는 "
http://developers.facebook.com/docs/reference/api/user"에서도 다음과 같이 명시되어 있습니다.
email : Requires email permission
만약, 여러분들의 웹 애플리케이션(또는 응용 프로그램)에서 사용자의 이메일 정보가 필요하다면 명시적으로 요청을 해야 합니다. 위에서 설명한 "<fb:login-button />" 버튼을 이용한 경우 다음과 같이 간단하게 처리가 됩니다.
<fb:login-button perms="...[요구되는 정보를 위한 권한 문자열]..."></fb:login-button>
제 웹 사이트의 경우 사용자 정보에서 "email"과 "user_website" 정보 2가지를 요구하기 때문에 다음과 같이 설정되어 있고,
<fb:login-button perms="email,user_website"></fb:login-button>
사용자는 최초 페이스북 로그인 시에 다음과 같이 확인을 받게 됩니다.
더욱 훌륭한 것은, 이메일 정보의 보호입니다. 사실, 자신이 사용하려는 웹 사이트가 이메일 정보를 요구한다면 "줄 수밖에 없는 상황"이 되어버리는 데요. (누군들, 사이트 약관을 읽어보고 정보 제공에 동의하고 싶겠습니까?) 페이스북은 이메일 주소를 외부적으로 노출되는 전용 이메일 계정을 별도로 제공해주는 데요. 이름하여 "proxied email"입니다. (사용자는 페이스북의 계정 정보 설정에서 이런 경우 "proxied email" 주소를 제공할 것인지, 실제 이메일 주소를 제공할 것인지를 선택할 수가 잇습니다.)
그래서, 페이스북 이외의 다른 응용 프로그램들은 원래의 사용자 이메일 정보를 알 수는 없고 페이스북에서 중계해주는 "proxied email" 주소만을 알 수 있습니다. 이에 대해서는 다음의 글에서 자세히 설명해 주고 있으니 참고하세요. ^^
Facebook App Notifications Moving to Your E-mail Inbox
; http://mashable.com/2010/01/20/facebook-applications-email/
사용자 정보 보호에 이런 세심함을 보여주는 웹 사이트를 보고 있노라니... 오히려 사용자 정보를 팔아먹는 못된 사이트들과 비교가 되는군요. ^^;
대부분의 외부 웹 응용 프로그램에서 취하는 형태가 바로 "페이스북 연동"일 것입니다. 기존 웹 애플리케이션 계정 정책에 페이스북 계정을 연동하기 위해서는 쿠키로부터 uid 값을 취해서 현재 "외부 웹 응용 프로그램"에 로그인한 사용자 계정과 연관지어 보관해 두어야 합니다.
access_token: ...[생략]...
base_domain: www.sysnet.pe.kr
expires: 1290085200
secret: ...[생략]...
session_key: ...[생략]...
sig: ...[생략]...
uid: 10302394932804
name : SeongTae Jeong
email: ...[생략]...
website: https://www.sysnet.pe.kr
이렇게 되면, 나중에는 페이스북 계정연동으로 인한 DB 자료들이 늘어나게 될 텐데요. 재미있는 점은, 사용자는 언제든지 아래에서 보는 것처럼 페이스북 웹 사이트로부터 여러분들의 웹 사이트와의 연동을 해제할 수 있다는 것입니다.
따라서 이런 상황이 되면 웹 사이트 DB 에는 더 이상 쓸모없는 페이스북 관련 연동 정보가 쌓여만 가는 상황이 되는 것입니다.
정상적이라면, 이런 경우 페이스북 측에서 "어플리케이션 제거" 링크를 사용자가 누를 때 해당 웹 사이트에 통지를 해주면 좋을 텐데요. 바로 이 기능을 위해서 응용 프로그램 설정 화면에서 "Deauthorize URL" 입력란이 있는 것입니다.
위에서는 "/user/removeuser.aspx" 웹 페이지를 부르도록 하고 있는데요. 페이스북은 사용자가 "어플리케이션 제거" 링크를 누르면 "removeuser.aspx" 호출 시에 POST 데이터에 여러 가지 정보를 넣어주는 데 이 중에서 "fb_sig_user" 값이 인증 시에 쿠키에 담겨 있던 "uid" 값이 되므로 사용자 정보를 DB에서 정상적으로 제거해 줄 수 있게 됩니다. 대략 다음과 같은 서버 측 코드를 구성해주면 됩니다.
public partial class removeuser : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string userId = Request.Form["fb_sig_user"];
if (string.IsNullOrEmpty(userId) == false)
{
...[DB에서 제거]...
}
}
}
물론... 하필 사용자가 "어플리케이션 제거"를 할 때 여러분들의 웹 서버가 멈춰있다면... 어쩔 수 없겠군요. ^^
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]