OBJECTIVE
You want to Login/Logout your user with just one click, regardless of the user being a FB user or your web site user. You don't want your users to use Facebook logout button
SCENARIOS
a. You have an ASP.NET web site, utilizing ASP.NET Forms authentication and also want to use Facebook Login /Logout functionality
b. You have multiple ASP.NET web sites and want to use “single sign on” for all of them, combining ASP.NET Forms authentication with Facebook Login.
I have tested this approach with the following IIS 7 setup:
one root web application, one sub-application and one virtual directory (both under the root web application)
PREREQUISITES
I presume you already know about the Facebook SDK for .NET.
If not, follow the instructions here:
http://facebooksdk.net/docs/web/getting-started
To be able to try the steps, described below, you must have a web application with Facebook Login enabled and tested, so you know it works.
To implement Single Sign On, you basically need to configure your web sites with the ASP.NET Memberhsip and Role providers and point them to a common database. In the Scenario B that’s easy to achieve as all three web sites share one master “Web.config” file. Here is an example from my working solution:
<authenticationmode="Forms">
<formscookieless="UseCookies"loginUrl="/YourVirtualDirectory/Account/Login.aspx" />
</authentication>
<machineKeydecryptionKey="AutoGenerate"validation="SHA1"validationKey="AutoGenerate" />
Facebook Logout combined with application logout
In case of Scenario B (three web applications sharing same user credentials) the biggest challenge would be to implement a single Logout.
The method, described in FB Developer’s tutorial shows how to implement a combined Login, using a generic HTTP handler “FacebookLogin.ashx” class.
public class FacebookLogin : IHttpHandler, System.Web.SessionState.IRequiresSessionState{
public void ProcessRequest(HttpContext context){
var accessToken = context.Request["accessToken"];
if (accessToken != null){
HttpContext.Current.Session["accessToken"] = accessToken;
..
}
}}
But the user’s AccessToken, stored in Session will be only available for the login-application and not for the other ones, if the user should fancy logging off from another site.
Therefore, it can be implemented, storing the AcessToken as a variable in a common helper class, available for all your applications.
In the following code snippets I call it “MyCommonClass”.
Facebook Login.ashx
public class FacebookLogin : IHttpHandler, System.Web.SessionState.IRequiresSessionState{
public void ProcessRequest(HttpContext context){
var accessToken = context.Request["accessToken"];
if (accessToken != null){
HttpContext.Current.Session["accessToken"] = accessToken;
MyCommonClass.accessToken = accessToken; // added code
..
}}}
Login.aspx.cs
protected void Page_Load(object sender, EventArgs e) {
// Do you stuff here in case of log in
#region logoff
if (this.Request.QueryString.ToString() == "logoff") {
/** Sign out off your app * */
SignOut();
// in case of FB login
string accT = null;
if (Session["accessToken"] != null)
accT = Session["accessToken"].ToString();
else{
accT = MyCommonClass.accessToken;
}
if (this.Request.UrlReferrer != null && this.Request.UrlReferrer != this.Request.Url){
string redirectUrl = this.Request.UrlReferrer.ToString();
// in case of FB login
if (MyCommonClass.IsFbUser(Membership.GetUser().UserName))
if (accT != null)
Response.Redirect(LogOut(accT, redirectUrl));
else{
Response.Redirect("/MyVirtualDir/FacebookLogout.ashx", true);
}
else
this.Response.Redirect(redirectUrl, true);
}
return;
}
#endregion
}
protected string LogOut(string accessToken, string url) { // FB logout
var oauth = new FacebookClient();
var logoutParameters = new Dictionary<string, object>{
{"access_token", accessToken},
{ "next", url}
};
var logoutUrl = oauth.GetLogoutUrl(logoutParameters);
return logoutUrl.ToString();
}
protected void SignOut(){ // App logout
FormsAuthentication.SignOut();
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, string.Empty);
cookie.Expires = DateTime.Now.AddYears(-3);
HttpContext.Current.Response.Cookies.Add(cookie);
}
Facebook Login.ashx
public class FacebookLogout : IHttpHandler {
public void ProcessRequest(HttpContext context) {
var accessToken = MyCommonClass.accessToken;
if (accessToken != null) {
string url = context.Request.UrlReferrer.ToString();
LogOut(accessToken);
MyCommonClass.accessToken = null;
context.Response.Redirect(url);
}
}
protected void LogOut(string accessToken) {
var oauth = new FacebookClient();
var logoutParameters = new Dictionary<string, object>{
{"access_token", accessToken},
{ "next", ""}
};
var logoutUrl = oauth.GetLogoutUrl(logoutParameters);
}