Social login is one of the most important features of an app, it’s the first interaction of an user with your work and has to be easy, simple and trustworthy. With this in mind, I decided, together with my friend @nosmirk, to start a series of posts with what we think are the best approaches to do social login with all the major social media players, let’s start with Facebook.
There are many plugins to use on Xamarin.Forms to implement authentication with Facebook, unfortunately for all the ones that I tried, the default option is display a WebView where the user has to type their Facebook credentials or deep link Facebook in the user’s browser. What if the user has Facebook app installed in his device?! We want our app to use it!
Xamarin has created Xamarin.Facebook.Android and Xamarin.Facebook.iOS, both available on nugget. They are a translation of Facebook’s native sdk into C#. We will use them to implement the native login flow for Facebook on Android and iOS with Xamarin.Forms.
Facebook App Setup
I won’t go into much detail on how to create a Facebook App, only how to set it up for what we want to do here. For detailed information, you can check @tim_lariviere post here, he did a great job explaining the step by step, you can also check out Facebook’s official docs here.
Once our Facebook App named AuthenticationExample is created and all set on the developers portal, go to Settings > Basic on the side menu, on this page, we will setup the access to iOS and Android platforms.
After this, select the “add platform button”, and add the Android and iOS options to our AuthenticationExample app.
Facebook Android Setup
To configure android a package name, a class name and a hash key are required. The Package name of the android app you can find at Xamarin.Android project, on the AndroidManifest.xml file, for the class name let’s use MainActivity and for the hash key you will need to open cmd or terminal and type changing the[USERNAME] tag to your own:
Mac: keytool -exportcert -alias androiddebugkey -keystore /Users/[USERNAME]]/.local/share/Xamarin/Mono\ for\ Android/debug.keystore | openssl sha1 -binary | openssl base64 Windows: keytool -exportcert -alias androiddebugkey -keystore "C:\Users\[USERNAME]\AppData\Local\Xamarin\Mono for Android\debug.keystore" | openssl sha1 -binary | openssl base64
The terminal or cmd will ask for a password than it will give you the hash key, paste the hash key and the package name on the Android platform and hit the save button on the bottom of the page.
Xamarin iOS Setup
For iOS the setup is simpler, just add the bundle id of our app to the iOS window and hit save at the bottom of the page.
Xamarin Android Project Setup
Now let’s setup our Xamarin.Droid project with the required information for it to work properly, you can also follow the guide made by Facebook here.
- Download Xamarin.Facebook.Android(vs4.26) SDK, on the Android project via nugget.
- Paste this on the strings.xml file /values/strings.xml, replace by the AuthenticationExample app id.
<string name="facebook_app_id"><YOUR APP ID></string>
- Open AndroidManifest.xml and add a user-permission element to the file
<application android:label="@string/app_name" ...> ... <meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/> ... </application>
- Open MainActivity.cs and inside OnCreate method, add Facebook SDK initialization.
protected override void OnCreate(Bundle bundle) { TabLayoutResource = Resource.Layout.tabs; ToolbarResource = Resource.Layout.toolbar; base.OnCreate(bundle); FacebookSdk.SdkInitialize(this); global::Xamarin.Forms.Forms.Init(this, bundle); LoadApplication(new App(new AndroidInitializer())); }
- Override the following method on MainActivity.cs.
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { base.OnActivityResult(requestCode, resultCode, data); var manager = DependencyService.Get<IFacebookManager>(); if (manager != null) { (manager as FacebookManager)._callbackManager.OnActivityResult(requestCode, (int)resultCode, data); } }
Xamarin iOS Project Setup
It is time for Xamarin.iOS find the info.plist file and open it in the xml editor.
- Download Xamarin.Facebook.iOS SDK(vs4.24), on the iOS project via nugget.
- Copy & Paste the XML snippet into the body of your file (inside the dict tag). Replace by the AuthenticationExample app id.
<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>fb<YOUR APP ID></string> </array> </dict> </array> <key>FacebookAppID</key> <string><YOUR APP ID></string> <key>FacebookDisplayName</key> <string>AuthenticationExample</string> <key>LSApplicationQueriesSchemes</key> <array> <string>fbapi</string> <string>fb-messenger-api</string> <string>fbauth2</string> <string>fbshareextension</string> </array>
- Open AppDelegate.cs and override the following methods.
public override void OnActivated(UIApplication uiApplication) { base.OnActivated(uiApplication); AppEvents.ActivateApp(); } public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation) { //return base.OpenUrl(application, url, sourceApplication, annotation); return ApplicationDelegate.SharedInstance.OpenUrl(application, url, sourceApplication, annotation); }
Let’s code!
Wow, that was a lot of configuration! Let’s get to coding now.
Me and my friend @nosmirk, built a repo on Github that has a working example, if you want, feel free to clone, fork and use it, you can find it here, under the FacebookNativeLogin folder. It is very simple, one page in Xamarin.Forms that uses Dependency Injection and delegates the Login and Logout actions to the native platforms, then via an Action, we receive the Facebook User data back in the Xamarin.Forms project.
Project Tech info
- Xamarin.Forms 2.4.0
- Prism 6.3.0
- Xamarin.Facebook.Android 4.26 (On the Xamarin.Droid project)
- Xamarin.Facebook.iOS 4.24 (On the Xamarin.iOS project)
On the Forms project, we have a contract with two signatures
public interface IFacebookManager { void Login(Action<FacebookUser, string> onLoginComplete); void Logout(); }
Both methods are implemented on Android project and on iOS project, after the execution of the login, the OnLoginComplete method will be invoked, adding the user facebook object to the ViewModel binding.
private void OnLoginComplete(FacebookUser facebookUser, string message) { if (facebookUser != null) { FacebookUser = facebookUser; IsLogedIn = true; } else { _dialogService.DisplayAlertAsync("Error", message, "Ok"); } }
What’s Next?
@nosmirk is also working on a Git repository that we will both keep working on and improving, also we will build social login with other social media there, so check it out!
I would like to give special thanks to @monkeynightsdev community that is always open to discuss and help each other. and an awesome thanks to @nosmirk and @junior_jaco, that helped me put up this post together!
CAUSER TIP:
- If you have trouble executing the hash command on windows, you will have to add the required System Variables so you are able to execute it.
- I had trouble with the latest version of the Xamarin.Facebook.iOS package, on a real device it wasn’t detecting the Facebook app installed in the user’s device, so I downgraded it from version 4.26 to 4.24. Then it worked perfectly.
throw new CauserException();
References
- https://github.com/mikeapple/XamarinFormsNativeFBLogin/
- https://github.com/xamarin/Xamarin.Auth
- https://github.com/HoussemDellai/Xamarin.Auth
- https://github.com/nosmirck/Xamarin.Forms.Social
- https://github.com/DanielCauser/SocialLoginSamples
- https://developers.facebook.com/quickstarts?platform=android
- https://developers.facebook.com/quickstarts?platform=ios
- https://developer.xamarin.com/guides/xamarin-forms/cloud-services/authentication/oauth/
- http://timothelariviere.com/2017/10/11/authenticate-users-through-facebook-using-xamarin-auth/
- https://developers.facebook.com/
- https://www.youtube.com/watch?v=cyq_ho4QflQ
- https://www.youtube.com/watch?v=YpkqOjw38ds&feature=youtu.be
Daniel , obrigado por compartilhar!
Só tenho uma dúvida, para implementar sem Prism? Na MainViewModel, recebe-se como parâmetros um FbManager, o que é necessário passar para ela?
LikeLiked by 1 person
Entao, essa classe FacebookManager, e injetada na ViewModel pelo container de DI que eu usei nesse projeto(Unity) que ja vem com o Prism. Voce pode injetar essa classe na tua viewmodel com o container de DI que usar no seu projeto.
LikeLike
Hey Daniel,
Thanks for the amazing efforts man, really helpful.
i’m following your article to implement fb login on android and ios
I’m getting a problem installing facebook sdk on the Android project.
it conflicts with the Xamarin Forms library, I always get this error
Version conflict detected for Xamarin.Android.Support.Compat. Reference the package directly from the project to resolve this issue.
testApp.Android -> Xamarin.Forms 2.5.0.91635 -> Xamarin.Android.Support.v7.MediaRouter 25.4.0.2 -> Xamarin.Android.Support.v7.Palette 25.4.0.2 -> Xamarin.Android.Support.Compat (= 25.4.0.2)
testApp.Android -> Xamarin.Facebook.Android 4.26.0 -> Xamarin.Android.Support.CustomTabs 25.3.1 -> Xamarin.Android.Support.Compat (= 25.3.1).
and I’ve been on this for a while now and I can’t seem to find any common compat library between the two libraries.
any ideas?
LikeLike
Hey! Have you tried to make the code in the repo run, using your own configurations?
Does your project run without the Facebook SDK? I’m not realy sure how to work around this since I can’t reproduce it on my end.
if you find a way around this, please post here or on the repo issues on git hub! So we can keep track of it and help others that may have the same problem!
LikeLike
You must use older packages: Xamarin.Forms 2.4.xx, Xamarin.Android.Support.Compat. I had same problem with Xamarin.Forms.Maps.
LikeLike
Thank you Harry for the feedback, Oscar also posted his thoughts, I think it is very helpfull!!
LikeLike
Hey Amr,
I found exactly the same problem. Stumped me for ages. However, eventually I realized that Xamarin.Android.Support.CustomTabs 26.1.0.1 (I’ve bound to Oreo in my project) has been pulled in as a dependency automated (I hadn’t installed it manually).
To get round this problem, I had to go to Nuget and install Xamarin.Android.Support.CustomTabs manually (with the same version that is already installed). After doing that, when I went to Xamarin.Facebook.Android package and was able to install it.
The weird thing is:
Xamarin.Facebook.Android 4.26.0 – > Xamarin.Android.Support.Compat 25.3.1 as displayed in the error message issued by nuget is misleading. If you look at the dependencies list on the Xamarin.Facebook.Android package, i says Xamarin.Android.Support.Compat >=25.3.1 (i.e. greater than or equal to), not = equal to. Not sure why that’s the case, but it doesn’t install without problems.
LikeLike
Thank you Oscar for the awesome feedback!
LikeLike
No resource found that matches the given name (at ‘value’ with value ‘@string/facebook_app_id’) error
how to solve
LikeLike
Hi Daniel
First of all I just want to say thank you for the Google And Facebook Native Plugin tutorials. I just wanted to know 2 things which are a bit off the topic and that you might just consider.
1. Since you have 2 native login methods and the methods with regard to the platform have slightly different implementations, but the viewmodel for the login view is more or less the same regardless of the platform, would it be possible to simplify the viewmodel and have for e.g on Login and one Logout method instead of having GoogleLogin, FacebookLogin, GoogleLogout, FacebookLogout?
2.Is it possible to call one of the login provider methods from anywhere in an application to find out whether or not a user is logged into a platform before logging them out.
Thank you sooo much Daniel.
I’d understand if you feel I’m asking for too much, thank you for your time.
LikeLike
Hi Daniel
I’m facing a problem with the Facebook Login for iOS, After I tap the button to login with Facebook, a webview opens and provides me with two options:
1.Login With Email Or Phone Number
2.Continue To Facebook Application(Login with Facebook application)
Well they’re not exactly in those words, but something to that effect.
After I select the option to login with the Facebook Application and confirm that I want to login, it returns back to my application but the webview with the two login options is still there. The only way the ‘call back’ function is fired is by cancelling the login by tapping on ‘Done’ in the top left of the dialog.
LikeLike
I figured this one out, it was a mistake on my behalf.
LikeLiked by 1 person
What was the mistake? I am having the exact same issue. Any help would be much appreciated.
LikeLike
I had to change my code in the AppDelegate from this:
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
UIApplicationOpenUrlOptions openUrlOptions = new UIApplicationOpenUrlOptions(options);
return SignIn.SharedInstance.HandleUrl(url, openUrlOptions.SourceApplication, openUrlOptions.Annotation);
}
which is Daniel’s Native Google Login Sample, if my memory serves me correctly
to this:
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
return ApplicationDelegate.SharedInstance.OpenUrl(application, url, sourceApplication, annotation);
}
which is in Daniel’s Facebook Native Login Sample, the above override works for both Google Login And Facebook Login.
Sorry for replying so late Ryan, I hope this helps you.
LikeLiked by 1 person
Thank you for sharing Clifton!!
LikeLike
No problem Daniel, happy to do so 🙂
LikeLiked by 1 person
I have another question though I was looking at the iOS code for the facebook login, when you’re assigning a value to the variables for example first_name or last_name, there’s a try catch block for each and every variable, why is this so, why not just have one try catch block for all of them.
LikeLike
can we do the same for login with Twitter ?
LikeLike
I belieave twitter also has a client sdk available!! I still need to work on a post for twitter 🙂
LikeLike
Hi Daniel,
thank you for this article..
I tried to make the code in the repo run but it didn’t . when I click facebook login it stuck on loading without opening the fb app or giving an error. any Idea how to solve this?
LikeLike
ok It seems that the app doesn’t work in debug mode.. after I run it without debug it works well but it does not ask to continue with this account it automatically get the logged in account on the FB app and if I logged out from the app it asks to choose a user.(Is this the normal behavior?)
LikeLike
Hey Chahid! Please post this issue in the github repo, it will be easy to track and to solve, and can help other people when we find what is wrong 🙂
LikeLike
I want to add some fixes to to keep up to date.
Android:
1 – You should change this line with the following:
-You need this plugin: https://github.com/jamesmontemagno/Xamarin.Plugins to get curreny activity.
var context = CrossCurrentActivity.Current.Activity;
LoginManager.Instance.LogInWithReadPermissions(context as Activity as Activity, new List { “public_profile”, “email” });
2- If you are getting “SERVER_ERROR: [code] 1675030 [message]: Error performing query. [extra]: null", there is something wrong about your configurations. For my case, it was Key Hash. I used wrong openssl version, it didn't ask me any password.
Download and install the right version of openssl from http://slproweb.com/products/Win32OpenSSL.html. (mine is Win64 OpenSSL v1.1.1 - 43mb)
and use following command:
keytool -exportcert -keystore "C:\Users\[USER]\AppData\Local\Xamarin\Mono for Android\debug.keystore" -alias androiddebugkey | "C:\Program Files\OpenSSL-Win64\bin\openssl" sha1 -binary | "C:\Program Files\OpenSSL-Win64\bin\openssl" base64
Enter keystore password: android
iOS: I will edit this entry, after I get things done.
LikeLike
I follow this steps and error 1675030 persist 😦
LikeLike
Its normal receive this message?
The JKS keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format
LikeLike
Hi, its a very useful code, but i have a problem, i need to unistall my facebook app to succesfuly login in my app with facebook, and i dont know why, if i have installed the facebook app, the login in my app with facebook doesnt work.
LikeLiked by 1 person