Native Facebook Login in Xamarin Forms iOS App
Many apps need some kind of user authentication. Instead of having users to register on your site, it’s more convenient to use existing Logins. Many social networks like Facebook, Twitter and Google offer to use their login data to authenticate users in your application.
You have 2 different options of authentication: Server side or client side. Server side implementation is quite easy. You could e.g. use Azure to handle all the authentication. Xamarin University has course AZR 120 about “Authentication with Azure” to guide you step by step. There is also information how to do Facebook Login without Azure, e.g. by HoussemDellai on github.
I’ve implemented this and more or less immediately users complaint about the login process because they need to enter their Facebook Name and their Facebook Password. Some find it just inconvenient, some others don’t even know their Facebook password anymore. They are logged in on their browser and on their smartphones and there is no need to enter the password anymore.
So current article is about the second option: Client side authentication. Facebook (and also Twitter, Google, …) has some SDKs available helping to authenticate a user without asking for their password.
There are already some existing articles about Native Android Facebook Authentication with Azure App Service by James Montemagno, Native iOS Facebook Authentication with Azure App Service by Mike James and also a github example by mikeapple showing native Facebook Client Login with Xamarin Forms iOS Project. And of course the Xamarin Facebook iOS SDK contains also helpful information.
Current article contains a step by step guide with information from several sources. In the app you’ll have a Xamarin Forms iOS project with native Facebook login as you could see on the animated gif.
Warning!
Do not try this at home iPhone Simulator! To see the advantage you need to have the Facebook App installed on the device, and that does not work on a Simulator. So make sure you do all your testing with a real device!
Update your Facebook App to allow iOS App Login
First let’s update your Facebook app at https://developers.facebook.com/apps/ because you need to tell Facebook that your app wants to authenticate using the Facebook iOS Native Login. So within your Facebook App, select Facebook Login – Quickstart at the left navigation. There you’ll find 10 steps. Most of them are not important for us as we have already added the SDK etc. So skip the first 2 steps and add your bundle identifier at Step 3. (You’ll find your bundle identifier as usual in your info.plist within your iOS project).
The next important step is step number 5. It contains necessary lines which need to be added to your info.plist. I’ve added the lines later on into the section where all changes for your iOS project are made. So you might do them now or later as you like. Just keep in mind that these lines are necessary to add to info.plist and now you know where they are from.
Now skip all the next steps as they are native iOS code and we don’t need them. At the end, in step 10 it says “Congrats, you’ve added Facebook Login to your iOS app! ” so that’s it for the facebook part.
Surprisingly there is no information anywhere on the dashboard or else that you have configured iOS Facebook Login successfull so don’t worry. If you go to Quickstart and select iOS again you’ll see in step 3 that your bundle identifier is still there so that’s fine.
Adding Facebook Native Login to PCL in Xamarin Forms
In the Xamarin Forms PCL you have to do the following changes / additions:
Add a new class “FacebookLoginButton.cs”
The class should be of type Button (line 5) from Xamarin Forms:
using System; namespace FacebookLoginNative { public class FacebookLoginButton : Xamarin.Forms.Button { public FacebookLoginButton() { } } }
Add FacebookLoginButton to your login page
Now add an instance of the new FaceboolLoginButton (line 7) to your login page, in current example FacebookLoginNativePage.xaml:
<?xml version="1.0" encoding="utf-8"?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:FacebookLoginNative" x:Class="FacebookLoginNative.FacebookLoginNativePage"> <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"> <local:FacebookLoginButton x:Name="fbLoginButton" Text="Login using Facebook" VerticalOptions="Center" HorizontalOptions="Center" /> <Label x:Name="fbLoginResult" VerticalOptions="Center" HorizontalOptions="Center" /> </StackLayout> </ContentPage>
Add action to App.xaml.cs
A new action has to be defined in your app.xaml.cs. This action is used later on for processing the result returned from Facebook:
using Xamarin.Forms; namespace FacebookLoginNative { public partial class App : Application { public static System.Action<string> PostSuccessFacebookAction { get; set; } public App() { InitializeComponent(); MainPage = new FacebookLoginNativePage(); } protected override void OnStart() { // Handle when your app starts } protected override void OnSleep() { // Handle when your app sleeps } protected override void OnResume() { // Handle when your app resumes } } }
Add action to main page
Now we could add the new action PostSuccessFacebookAction to our .cs file of the login page:
using Xamarin.Forms; namespace FacebookLoginNative { public partial class FacebookLoginNativePage : ContentPage { public FacebookLoginNativePage() { InitializeComponent(); App.PostSuccessFacebookAction = token => { fbLoginResult.Text = token; }; } } }
Adding Facebook Native Login to iOS in Xamarin Forms
Now the following changes have to be done in the iOS project.
Add Xamarin Facebook iOS nuget package
nuget package Xamarin.Facebook.iOS is maintained by Xamarin. Just add the latest package to your iOS project. UPDATE (21. Sept. 2017): There seems to be a problem with latest release 4.26.0 so I rolled back to 4.24.0 where everything works fine. Not sure whether problem is related to iOS 11 which I updated in the meantime, but with 4.24.0 it works as expected.
Add Facebook Data to AppDelegate.cs
Now add the Facebook AppID and the Display Name to your AppDelegate.cs and also add OpenUrl and OnActivated to your AppDelegate:
using Foundation; using UIKit; namespace FacebookLoginNative.iOS { [Register("AppDelegate")] public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate { public override bool FinishedLaunching(UIApplication app, NSDictionary options) { Facebook.CoreKit.Settings.AppID = "1910612712502306"; Facebook.CoreKit.Settings.DisplayName = "XamAuthTest"; global::Xamarin.Forms.Forms.Init(); LoadApplication(new App()); Facebook.CoreKit.ApplicationDelegate.SharedInstance.FinishedLaunching(app, options); return base.FinishedLaunching(app, options); } public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation) { return Facebook.CoreKit.ApplicationDelegate.SharedInstance.OpenUrl(application, url, sourceApplication, annotation); } public override void OnActivated(UIApplication uiApplication) { base.OnActivated(uiApplication); Facebook.CoreKit.AppEvents.ActivateApp(); } } }
Update info.plist
Some additions have to be made to info.plist file. Remember? These are the lines provided by facebook in step 5 of the iOS registration. Go back to the top of current article to find the necessary information. Of course you need to set your App ID and your App Name.
Instead of doing them within Visual Studio it might be easier to use a code editor like Visual Studio Code.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDisplayName</key> <string>FacebookLoginNative</string> <key>CFBundleName</key> <string>FacebookLoginNative</string> <key>CFBundleIdentifier</key> <string>de.dotnetco.test.FacebookLoginNative</string> <key>CFBundleShortVersionString</key> <string>1.0</string> <key>CFBundleVersion</key> <string>1.0</string> <key>LSRequiresIPhoneOS</key> <true/> <key>MinimumOSVersion</key> <string>8.0</string> <key>UIDeviceFamily</key> <array> <integer>1</integer> <integer>2</integer> </array> <key>UILaunchStoryboardName</key> <string>LaunchScreen</string> <key>UIRequiredDeviceCapabilities</key> <array> <string>armv7</string> </array> <key>UISupportedInterfaceOrientations</key> <array> <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> <key>UISupportedInterfaceOrientations~ipad</key> <array> <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortraitUpsideDown</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> <key>XSAppIconAssets</key> <string>Assets.xcassets/AppIcon.appiconset</string> <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>fb1910612712502306</string> </array> </dict> </array> <key>FacebookAppID</key> <string>1910612712502306</string> <key>FacebookDisplayName</key> <string>XamAuthTest</string> <key>LSApplicationQueriesSchemes</key> <array> <string>fbapi</string> <string>fb-messenger-api</string> <string>fbauth2</string> <string>fbshareextension</string> </array> </dict> </plist>
Add FacebookLogin Button Renderer
The following new class has to be added to the iOS project:
using UIKit; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; using Facebook.LoginKit; using Facebook.CoreKit; using FacebookLoginNative; using FacebookLoginNative.iOS; [assembly: ExportRenderer(typeof(FacebookLoginButton), typeof(FacebookLoginButtonRendererIos))] namespace FacebookLoginNative.iOS { public class FacebookLoginButtonRendererIos : ButtonRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e) { base.OnElementChanged(e); if (Control != null) { UIButton button = Control; button.TouchUpInside += delegate { HandleFacebookLoginClicked(); }; } if (AccessToken.CurrentAccessToken != null) { App.PostSuccessFacebookAction(AccessToken.CurrentAccessToken.ToString()); } } void HandleFacebookLoginClicked() { if (AccessToken.CurrentAccessToken != null) { App.PostSuccessFacebookAction(AccessToken.CurrentAccessToken.ToString()); } else { var window = UIApplication.SharedApplication.KeyWindow; var vc = window.RootViewController; while (vc.PresentedViewController != null) { vc = vc.PresentedViewController; } var manager = new LoginManager(); manager.LogInWithReadPermissions(new string[] { "public_profile" }, vc, (result, error) => { if (error == null && !result.IsCancelled) { App.PostSuccessFacebookAction(result.Token.ToString()); } }); } } } }
And that’s all. Now you should be able to start this app on your device and authenticate via your facebook app.
And if you start it on your emulator (or on your iPhone without the Facebook app installed), don’t worry: It will show the Facebook Login Webpage so it’s fine to use the SDK and the above procedure also without Facebook app installed.
You could download a zipped sample application here: FacebookLoginNative
This is great. I loved how clear and objective you are with your tutorials.
I got stuck on a problem though … The login button is invisible. I mean, it’s still there, I can click it, but it’s invisible.
Do you have any approach for that?
Thank you
Sorry Pedro, no idea about that, hadn’t had this problem myself 🙁
can you please share the source code?
Hi Abel,
Please try downloading again. I refreshed the zip file at the end of the article.
Saved my month!