title: How to Create Facebook OAuth in WPF & C#
body: <p>I am developing a WPF application that requires me to get an Access Token from <a href="https://developers.facebook.com/docs/reference/dialogs/oauth/" rel="noreferrer" title="Facebook Login Dialog">Facebook using oAuth</a>. After much searching online, I came to the following conclusions:</p>
  
  <ol>
  <li>OAuth must be done in a browser</li>
  <li>I need to watch the URL posts in that browser, therefor it would have to be inside a <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.webbrowser%28v=vs.110%29.aspx" rel="noreferrer" title="MSDN : WebBrowser">WebBrowser</a> WPF control</li>
  </ol>
  
  <p>I decided to create a Modal Dialog for doing the Facebook authentication, and I can just take the Access Token and ignore the rest. I wanted to keep to the MVVM model but it was more difficult than I anticipated. <em>Any ideas on how to do that would be very helpful</em></p>
  
  <p>Here are some features that I implemented</p>
  
  <ul>
  <li><strong>Cookie deletion</strong> so could have another user authenticate without needing to log the current user out</li>
  <li><strong>Disable new account creation</strong> since it led to a weird UI experience</li>
  <li><strong>Listening to the cancel button</strong> from the javascript generated by Facebook</li>
  </ul>
  
  <h1>The WPF Window</h1>
  
  <p>The WPF is very simple. In essence it is just a WebBrowser control with the Navigated and Navigating events hooked up.</p>
  
  <pre><code>&lt;Window x:Class="FacebookAuthenticator.FacebookAuthenticationWindow"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          Title="Authenticate Facebook" 
          Height="600" 
          Width="600" 
          ResizeMode="NoResize" 
          WindowStyle="ToolWindow"&gt;
  &lt;Grid&gt;
      &lt;WebBrowser Name="webBrowser" 
                  Navigated="webBrowser_Navigated" 
                  Navigating="webBrowser_Navigating" /&gt;
  &lt;/Grid&gt;
  </code></pre>
  
  <p></p>
  
  <h1>The Code</h1>
  
  <pre><code>//The Application ID from Facebook
  public string AppID {get; set; }
  
  //The access token retrieved from facebook's authentication
  public string AccessToken {get; set; }
  
  public FacebookAuthenticationWindow()
  {
      InitializeComponent();
      this.Loaded += (object sender, RoutedEventArgs e) =&gt;
      {
          //Add the message hook in the code behind since I got a weird bug when trying to do it in the XAML
          webBrowser.MessageHook += webBrowser_MessageHook;
  
          //Delete the cookies since the last authentication
          DeleteFacebookCookie();
  
          //Create the destination URL
          var destinationURL = String.Format("https://www.facebook.com/dialog/oauth?client_id={0}&amp;scope={1}&amp;display=popup&amp;redirect_uri=http://www.facebook.com/connect/login_success.html&amp;response_type=token",
             AppID, //client_id
             "email,user_birthday" //scope
          );
          webBrowser.Navigate(destinationURL);
      };
  }
  </code></pre>
  
  <h2>Getting the Access Token</h2>
  
  <p>I forgot exactly where I got this code (if someone can remind me so that I could give proper credit I would be grateful).</p>
  
  <pre><code>private void webBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
  {
      //If the URL has an access_token, grab it and walk away...
      var url = e.Uri.Fragment;
      if (url.Contains("access_token") &amp;&amp; url.Contains("#"))
      {
          url = (new System.Text.RegularExpressions.Regex("#")).Replace(url, "?", 1);
          AccessToken = System.Web.HttpUtility.ParseQueryString(url).Get("access_token");
          DialogResult = true;
          this.Close();
      }
  }
  </code></pre>
  
  <h2>Deleting Cookies</h2>
  
  <p>I realized that after someone logged in, there status stayed that way and would not allow someone else to log in. I decided to remove the cookies in the beginning of each authentication in order to prevent this.</p>
  
  <pre><code>private void DeleteFacebookCookie()
  {
      //Set the current user cookie to have expired yesterday
      string cookie = String.Format("c_user=; expires={0:R}; path=/; domain=.facebook.com", DateTime.UtcNow.AddDays(-1).ToString("R"));
      Application.SetCookie(new Uri("https://www.facebook.com"), cookie);
  }
  </code></pre>
  
  <h2>No New Accounts</h2>
  
  <p>Allowing the user to create a new account led to a weird UI experience. For my use cases, the user should already have an exsiting account. I disabled this by checking if the user was redirected to "r.php/" which is what Facebook uses to create a new account.</p>
  
  <pre><code>private void webBrowser_Navigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e)
  {
      if (e.Uri.LocalPath == "/r.php")
      {
          MessageBox.Show("To create a new account go to www.facebook.com", "Could Not Create Account", MessageBoxButton.OK, MessageBoxImage.Error);
          e.Cancel = true;
      }
  }
  </code></pre>
  
  <h2>Handling window.close()</h2>
  
  <p>The cancel button in Facebook's dialog shows the ability to close the window. I needed to catch this and make sure to close the window. I had no idea how but I saw that in the MessageHook I was able to see that the last message to be sent (int msg) each time was 130, so I just listened for 130. It's sloppy, but it works.</p>
  
  <pre><code>IntPtr webBrowser_MessageHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
  {
      //msg = 130 is the last call for when the window gets closed on a window.close() in javascript
      if (msg == 130)
      {
          this.Close();
      }
      return IntPtr.Zero;
  }
  </code></pre>
  
  <h1>Summary</h1>
  
  <p>Using the code is pretty simple</p>
  
  <pre><code>FacebookAuthenticationWindow dialog = new FacebookAuthenticationWindow() { AppID = "YOURAPPID" };
  if(dialog.ShowDialog() == true)
  {
      string accessToken = dialog.AccessToken;
      //The world is your oyster
  }
  </code></pre>
  
  <p>I hope this example is helpful to the community. I would really like to hear from anyone who has any improvements, insights or even criticism.</p>
  
  <p>~Mo</p>