DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Curious about the future of data-driven systems? Join our Data Engineering roundtable and learn how to build scalable data platforms.

Data Engineering: The industry has come a long way from organizing unstructured data to adopting today's modern data pipelines. See how.

Threat Detection: Learn core practices for managing security risks and vulnerabilities in your organization — don't regret those threats!

Managing API integrations: Assess your use case and needs — plus learn patterns for the design, build, and maintenance of your integrations.

Related

  • Login With Facebook and Google Using Angular 8
  • Custom Domains for HTTP/2 on Heroku
  • Unlock AI Power: Generate JSON With GPT-4 and Node.js for Ultimate App Integration
  • 5 Simple Steps To Get Your Test Suite Running in Heroku CI

Trending

  • Monitoring Kubernetes Service Topology Changes in Real Time
  • Reactive Kafka With Spring Boot
  • How Jenkins Can Stay Relevant in the Next Decade
  • Effective Methods to Diagnose and Troubleshoot CPU Spikes in Java Applications

Custom oAuth Login to Facebook for Windows Store Apps

By 
Joost van Schaik user avatar
Joost van Schaik
·
Jun. 26, 15 · Opinion
Likes (0)
Comment
Save
Tweet
Share
1.8K Views

Join the DZone community and get the full member experience.

Join For Free

Intro: the joy of third party dependencies
At Wortell I am currently working on an app that uses some kind of Facebook integration. Last Friday (June 20) something odd occurred: some POC code that I got from my awesome colleague Melvin Vermeer where I had been toying with, suddenly stopped working. Assuming I had messed something up, I started tinkering with it, then checked the Facebook settings to see if Melvin had used some odd setting that only worked temporarily. This was not the case – so I even tried it on a different computer and later at home (operating on the assumption I had somehow blacklisted the Wortell offices). To no avail. The error I kept getting was:

Given URL is not permitted by the Application configuration
One or more of the given URLs is not permitted by the App's settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App's domains.

Not a good way to start a weekend, I can tell you. Then I decided to employ the ‘wisdom of the crowd’, aka twitter. My fellow MVP András Vélvart responded immediately by acknowledging he had the same problem, and pointed me to this Facebook bug report.

I hadn’t messed anything up, neither had Melvin. Facebook itself had pulled the rug from under us.

Now at the point of this writing I have ascertained Facebook apparently have fixed the error, but that was not the case yesterday with a deadline looming I needed a plan B, and I got one with the help of Tamás Deme, aka 'tomzorz', a Hungarian Windows Phoneconsumer MVP that I did not knew nor followed yet (shame on me!). Although the ‘normal’ way now works again, I decided to blog about the alternative approach anyway, to make sure this plan B is available to everyone in case, ehm … excrement hits the cooling device … again.

The prescribed way of getting a Facebook access token
In a world where everything works as it should you can get a Facebook token using WebAuthenticationBroker and a Facebook C# SDK, which is also available as a NuGet package. The code I got from my colleague basically came down to this:

using Facebook;

namespace FacebookNormal
{
  public sealed partial class MainPage : Page
  {
    private const string AppId = "your app id here";
    private const string ExtendedPermissions = 
      "publish_actions, user_managed_groups, user_groups";

    public MainPage()
    {
      this.InitializeComponent();
    }

    private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
      var result = await AuthenticateFacebookAsync();
      var md = new MessageDialog("your token is: " + result);
      await md.ShowAsync();
    }

    private async Task<string> AuthenticateFacebookAsync()
    {
      try
      {
        var fb = new FacebookClient();

        var redirectUri = 
          WebAuthenticationBroker.GetCurrentApplicationCallbackUri().ToString();

        var loginUri = fb.GetLoginUrl(new
                                       {
                                         client_id = AppId,
                                         redirect_uri = redirectUri,
                                         scope = ExtendedPermissions,
                                         display = "popup",
                                         response_type = "token"
                                       });

        var callbackUri = new Uri(redirectUri, UriKind.Absolute);

        var authenticationResult =
          await
            WebAuthenticationBroker.AuthenticateAsync(
            WebAuthenticationOptions.None, 
            loginUri, callbackUri);

        return ParseAuthenticationResult(fb, authenticationResult);
      }
      catch (Exception ex)
      {
        return ex.Message;
      }
    }

    public string ParseAuthenticationResult(FacebookClient fb, 
                                            WebAuthenticationResult result)
    {
      switch (result.ResponseStatus)
      {
        case WebAuthenticationStatus.ErrorHttp:
          return "Error";
        case WebAuthenticationStatus.Success:

          var oAuthResult = fb.ParseOAuthCallbackUrl(new Uri(result.ResponseData));
          return oAuthResult.AccessToken;
        case WebAuthenticationStatus.UserCancel:
          return "Operation aborted";
      }
      return null;
    }
  }
}

You get the callback URL to your own app, create a login Url, ask the WebAuthenticationBroker to do it’s stuff and show the “connecting to a service” window with the Facebook login, you parse the result, and if all goes well, you have a token. All code sits in the code behind – this was a POC, so that is very much OK.

Plan B – using a custom login using a WebViewThis looks very much the same, except that I have replaced both the AuthenticateFacebookAsync and the ParseAuthenticationResult methods.

private const string FbSuccess = 
  "https://www.facebook.com/connect/login_success.html";

private async Task<string> AuthenticateFacebookAsync()
{
  try
  {
    var fb = new FacebookClient();

    var loginUri = fb.GetLoginUrl(new
    {
      client_id = AppId,
      redirect_uri = FbSuccess,
      scope = ExtendedPermissions,
      display = "popup",
      response_type = "token"
    });

    var authenticationResult =
      await
        FacebookAuthenticationBroker.AuthenticateAsync(loginUri);

    return ParseAuthenticationResult(authenticationResult);
  }
  catch (Exception ex)
  {
    return ex.Message;
  }
}

private static string ParseAuthenticationResult(string authResult)
{
  var pattern = 
    string.Format("{0}#access_token={1}&expires_in={2}", 
                  FbSuccess,"(?<access_token>.+)", "(?<expires_in>.+)");
  var match = Regex.Match(authResult, pattern);
  return match.Groups["access_token"].Value;
}

Now what is that mysterious FacebookAuthenticationBroker? The framework for that I got from Tamás, and I added some stuff to it

namespace FacebookCustom
{
  /// 

  /// This class is a helper to replace the default WebAuthenticationBroker
  /// 

  public static class FacebookAuthenticationBroker
  {
    public static Task AuthenticateAsync(Uri uri)
    {
      var tcs = new TaskCompletionSource();

      var w = new WebView
      {
        HorizontalAlignment = HorizontalAlignment.Stretch,
        VerticalAlignment = VerticalAlignment.Stretch,
        Margin = new Thickness(30.0),
      };

      var b = new Border
      {
        Background = 
          new SolidColorBrush(Color.FromArgb(255, 255, 255, 255)),
        Width = Window.Current.Bounds.Width,
        Height = Window.Current.Bounds.Height,
        Child = w
      };

      var p = new Popup
      {
        Width = Window.Current.Bounds.Width,
        Height = Window.Current.Bounds.Height,
        Child = b,
        HorizontalOffset = 0.0,
        VerticalOffset = 0.0
      };

      Window.Current.SizeChanged += (s, e) =>
          {
            p.Width = e.Size.Width;
            p.Height = e.Size.Height;
            b.Width = e.Size.Width;
            b.Height = e.Size.Height;
          };

      w.Source = uri;

      w.NavigationCompleted += (sender, args) =>
      {
        if (args.Uri != null)
        {
          if (args.Uri.OriginalString.Contains("access_token"))
          {
            tcs.SetResult(args.Uri.ToString());
            p.IsOpen = false;
          }
          if (args.Uri.OriginalString.Contains("error=access_denied"))
          {
            tcs.SetResult(null);
            p.IsOpen = false;
          }
        }
      };

      p.IsOpen = true;
      return tcs.Task;
    }
  }
}

A lot of it is just setting up a UI of a popup with a WebView, then navigating to the Facebook authentication url. This will show a ‘normal’ web Facebook login (without the “Connecting to service” header). The interesting part I annotated in red and bold – when this event handler detects either “access_token” or “error=access_denied” in the url it’s navigated to, it considers it’s work done. Facebook navigates to a page with an url that either contains one of these strings, and we have a token again. Or not.

I know, it’s crude, probably has a lot of edge cases, but it will get you through the day when time is tight ;)

One more thing
To get this to work, you will have to add in your Facebook app settings (on Facebook developer) under section “Settings/Advanced” the return url to whatever you decided to use for the Facebook success url ( see FbSuccess constant).

image

Conclusion
As always you can find a ready to run demo on GitHub although in this case ‘ready to run’ is stretching it a little, as you will need to define an app in Facebook developer to get this actually working. And a great big of thanks to my colleague and the awesome #wpdev community for getting this to work.

facebook app

Published at DZone with permission of Joost van Schaik, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Login With Facebook and Google Using Angular 8
  • Custom Domains for HTTP/2 on Heroku
  • Unlock AI Power: Generate JSON With GPT-4 and Node.js for Ultimate App Integration
  • 5 Simple Steps To Get Your Test Suite Running in Heroku CI

Partner Resources


Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: