Facebook API login flow for desktop application

Facebook like

When developing desktop applications that interacts with Facebook you have to implement the login flow your self. After the login flow completes you can use the normal Facebook SDK libraries by supplying it with the access token your received. When implementing the login flow you have to make sure that you receive the access you requested. You can get a partial approval by the user and not be able to access all the scopes you need. In this example I have implemented the Facebook login flow into a C# .Net desktop application. Full source is available for download.

Basics of the Facebook login flow

Most of the information about how to implement your own Facebook login flow can be found in Facebook’s developers article Manually Build a Login Flow. The basics for doing this from a desktop application is to send the user to the Facebook site for authentication in a web browser control. This is the same way a web application would be implemented but instead of using return (redirect_uri) that goes back to your server you send the user to https://www.facebook.com/connect/login_success.html instead. The returned information will then be added as url fragments. Url fragments are also know as bookmarks, the information behind the # in an url. At the same time any errors will be passed back as query string parameters, behind the ? in the url, so you have to check for that as well. Besides from that the implementation is pretty straight forward.


Before you can send the user into the login flow you need to register a Facebook application. Use the “advanced setup” option to create it. After your created your application make a note of the application ID for later. Then go in to the application settings and select the “advanced” tab. Make sure that your set the following:

  • Native or desktop app? – Yes
  • Client OAuth login – Yes
  • Embedded browser OAuth Login – Yes

Display the dialog

FBDialog fbd = new FBDialog({your-application-id}, {comma-delimited-list-of-scopes});

This will show the Facebook login dialog. The implementation attached in the example code uses an extended version of the windows form web browser control. This extended version is used to be able to detect the javascript trying to close the dialog. The code for this extension is included in the example. Credit to Mrojas @ Artinsoft, the original code and article.

When the dialog loads the return url, mentioned above, and the comma delimited list of scopes are url encoded. Then we build the url and navigate to it.

string returnURL = WebUtility.UrlEncode("https://www.facebook.com/connect/login_success.html");
string scopes = WebUtility.UrlEncode(p_scopes);
FBwebBrowser.Url = new Uri(string.Format("https://www.facebook.com/dialog/oauth?client_id={0}&redirect_uri={1}&response_type=token%2Cgranted_scopes&scope={2}&display=popup", new object[] { p_appID, returnURL, scopes }));

We also attach an event handler for when the browser navigates.

FBwebBrowser.Navigated += FBwebBrowser_Navigated;

The login flow

Now the user is presented with the login screen and information about what application they will authenticate by logging in. The user have several options here:

  • The user can click cancel at once and close the dialog. The FBDialog will then return DialogResult.Cancel.
  • The user can login and authenticate your app but edit the scopes you are allowed to access. FBDialog will then return DialogResult.OK and you will be able to retrieve which scopes was approved. See below under “Return values”.
  • The user can login and then click abort/cancel. The FBDialog will then return DialogResult.Abort. This will also be the result in case of an error. See below under “Return values”.

During the users interaction with the login flow the FBwebBrowser_Navigated function will fire every time the browser navigates to a new page/url. During this it will just set the title of the window to the same as the current document title until it hits the return url.

[csharp smarttabs=”true” tabsize=”4″]
if (FBwebBrowser.Url.AbsolutePath == "/connect/login_success.html")
// Check for error
if (FBwebBrowser.Url.Query.Contains("error"))
// Error detected
this.result = System.Windows.Forms.DialogResult.Abort;
ExtractURLInfo("?", FBwebBrowser.Url.Query);
this.result = System.Windows.Forms.DialogResult.OK;
ExtractURLInfo("#", FBwebBrowser.Url.Fragment);
// Close the dialog

If an error is detected it will extract the error information, which is then available as public properties on the FBDialog object and return DialogResult.Abort. If the login is successful access token, expires and granted scopes will be available as public properties on the FBDialog object and it will return DialogResult.OK.

Return values

The dialog returns a standard DialogResult that can be used like this:

[csharp smarttabs=”true” tabsize=”4″]
switch (fbd.ShowDialog(this))
    case DialogResult.Abort: // There was an error
    case DialogResult.Cancel: // User clicked cancel or closed the dialog
    case DialogResult.OK: // Logon successfull

If DialogResult.Abort is returned there are three public read-only properties available on the FBDialog object.

  1. FBDialog.error – name/type of the error
  2. FBDialog.error_reason – why the error was raised
  3. FBDialog.error_description – a brief description of the error

If DialogResult.Cancel is returned the user clicked cancel before logging in or closed the dialog.

If DialogResult.OK is returned the user logon was successful. However the user might not have granted you all the scopes you requested. There are several public read-only properties with information after a successful login.

  1. FBDialog.access_token – the access token string that can then be used for further requests against Facebook APIs.
  2. FBDialog.token_expires – a DateTime object representing the when the access token expires.
  3. FBDialog.granted_scopes – a comma separated list of scopes that the user granted you access to.
  4. FBDialog.denied_scopes – a comma separated list of scopes that the user denied you access to.


The implementation is pretty straight forward to use. The modification to the web browser control is only cosmetic but makes the flow work as users are use to in online apps. When you have received your access token you can use the Facebook SDK .Net for further interaction with the API. A great way to check out what you can do with the Graph API and what properties will be available on the objects is to use the Facebook Graph API explorer. Some scopes needs additional permissions from Facebook to use, but are all available to you for testing during the development process, more information is available on the Facebook Developers site.

This code can be used by anyone for any purpose but please link back and give credit!

Source code: [wpdm_file id=7]
Source code @ Github

26 Comments on “Facebook API login flow for desktop application”

  1. Hey,

    im just implementing facebook within desktop app, just on OS X (modified ios facebook sdk with ui elements changed). I`ve encountered weird problem with cookies crucial to keep user logged in are set to be session only (even after checking keep me logged in option), for just one session after logging in everything works fine. All settings seems to be same as yours. I was wondering if you had the same problem and if so how to solve this?

    Thanks in advance


  2. Hi,

    Haven’t really thought about that since it’s a desktop application. So every time the user runs my application I want them to authenticate. How ever in my example I use the standard webbrowser control included in .Net and that caches just like IE would do. So the next time I run the application and send the user to the auth screen it will just flash by and I get the token back.

    However this login flow is on a session basis. So if you need to keep the token alive for doing stuff in the background you might not be able to do that. In the past you could request an offline token that could be renewed at any time by your server or application to be able to access the API even if the user ended the session. I’m not sure if that is possible any more at least not with this login flow.

    You can read more about different tokens here: https://developers.facebook.com/docs/facebook-login/access-tokens



  3. I am getting this:

    You are not logged in: You are not logged in. Please log in and try again.


  4. Thank you so much for this.. I wrote my own version , but was getting a bit frustrated with it. ( I was trying to do it in a background thread so I only had to show the browser when required..so I could find out if the user was logged in etc but failed!). It’s been a real bonus being able to re-use yours and delete all my mine 🙂

    Only thing I added was to give an optional param to the ‘new’ called ‘rerequest’ ( I’m a VB coder sorry!) If set to true, it adds auth_type=rerequest to the auth logon URL.

    Without this , there is no way to re ask for a scope that was previously rejected,

    Thank you so much



    • I’m happy it helped! I will actually do a new implementation off this code in an upcoming project and I haven’t really reflected over the previously rejected scopes. You know why you are a VB coder? Because you can’t see sharp… 😉


  5. Hah, I can do C# , but I always end up going back to VB. Been doing it for too many years (20ish). ( Plus I have too many other languages I work with every day , means I always go back to what I am most comfortable with when I get a choice ) .
    I always get stick from C # coders though.. oh well, I’ll stay 2nd class 😛
    I’ll have a look out for the new version 🙂


    • I started out as a basic programmer my self went through vb, several versions prior to .net. I fall back to it every now and then but juggling multiple languages the syntax in C#, java and python are more similar so it’s easier to stick to that. Thank you for taking the time to write a few comments, really enjoy getting the feedback!


  6. Hello there,
    We have been developing a WPF application. Some users are encountering this problem at facebook login section. I am looking forward to your help at
    this point. Besides, those users who use any explorer version older than than Explorer 10 version cannot enter at all. Our most important problem right now
    is the one that I mentioned below.


    • Hi, as far as I can see the second one you get is a success message. The error message doesn’t say much since it’s not in English. Make sure you have the proper return url configured for the Facebook app in the dev console.


  7. After I login with my account, It thow an exception:
    “Sorry, something went wrong.
    We’re working on getting this fixed as soon as we can.”


  8. how can i log in with different accounts, after the first time the app logs in with my personal account, please help me!


  9. Hey Kristofer!

    I get this::

    Can’t Load URL: The domain of this URL isn’t included in the app’s domains. To be able to load this URL, add all domains and subdomains of your app to the App Domains field in your app settings.

    any help would be appreciated


  10. Hi,

    I managed to do a login using this sample – many thanks for it!

    But I ran into a problem: when requesting scopes, the buttons in those forms are not clickable. It works if pressing TAB to navigate to the button, then press ENTER.

    Facebook support told me: “we don’t support this”…
    More details: https://developers.facebook.com/support/bugs/307661020223552/

    Is this a configuration problem on my side or a facebook bug?

    Best regards



    • This example had been around for a few years. I suspect that the procedures has changed when it comes to scoops. So you properly have to modernize the code somewhat to handle scopes.


      • Thanks for the reply.

        In my real app, this is not an issue because the scopes will be defined in the facebook app definition.

        But I wanted to post the issue here – maybe it helps others to work around the “seems to be not usable” form, and maybe someone has an idea. It might also be a configuration issue in my app.

        Unfortunately, the WebBrowser control does not provide any methods to debug client side issues – it might be some JavaScript problem.

        Best regards



Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: