Facebook Logout combined with ASP.NET application logout

by pinkbegemot 7. May 2013 13:14

 

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);    

         }

 

 

Change language