2
votes

Is there a way to authenticate a user through Facebook in mvvmcross framework? I'm currently attempting use Mobile Azure Service to authenticate to Facebook, but I don't have any success. Without using mvvmcross, I can authenticate just fine.

Thank You! Mark

1

1 Answers

6
votes

In the MVVM sense what I've found is that no, you can not. Properties on the facebook login page are not bindable, nor should they be and is best treated as a modal view out of your control

What I would do is make it a view concern and use Xamarin.Auth to authenticate.

As an example let's say that you had a LoginView and LoginViewModel.

The LoginView provides your standard login Email/Password but with an option (button) to authenticate via facebook

From that view hook up to the touchupinside event of the facebooklogin button

this.btnFacebookLogin.TouchUpInside += (object sender, EventArgs e) =>
{
    DoFacebookLogin ();
}

Then in your DoFacebookLogin method 'present' the viewcontroller for facebook as described here https://github.com/xamarin/Xamarin.Auth/blob/master/GettingStarted.md

For example :

private void DoFacebookLogin ()
{
    var auth = new OAuth2Authenticator (
        clientId: "yournumericclientidhere",
        scope: "",
        authorizeUrl: new Uri ("https://m.facebook.com/dialog/oauth/"),
        redirectUrl: new Uri ("http://www.facebook.com/connect/login_success.html"));

        auth.AllowCancel = true;

        auth.Completed += (sender, eventArgs) => {
            DismissViewController (false, null);
            if (eventArgs.IsAuthenticated) {
                string user = eventArgs.Account.Serialize ();
                var messenger = Mvx.Resolve<IMvxMessenger> ();
                messenger.Publish (new FacebookLoggedIn (user));
            } else {
                // Cancelled here
            }
        };

        var vc = auth.GetUI ();
        this.PresentViewController (vc, true, null);
    }

Cancelled does not need to be handled since the modal viewcontroller will take you back to your LoginView

On success that viewcontroller is dismissed then I would use mvx's interpretation of an eventaggregator (plugins.messenger) to send a message to the viewmodel that the facebook modal view is closed, with that message you can pass the account details - accesstoken etc back to the viewmodel to do as you wish.

View (as above) :

string user = eventArgs.Account.Serialize();
var messenger = Mvx.Resolve<IMvxMessenger> ();
messenger.Publish (new FacebookLoggedIn (user));

Message Class in your PCL :

public class FacebookLoggedIn : MvxMessage
{
    public FacebookLoggedIn(object sender) : base(sender) {}
}

ViewModel also in your PCL :

public LoginViewModel()
{
    var messenger = Mvx.Resolve<IMvxMessenger> ();
    user = messenger.SubscribeOnMainThread<FacebookLoggedIn> (OnFacebookLoggedIn);
}

private void OnFacebookLoggedIn (FacebookLoggedIn MvxMessage)
{
    ... do something with the accesstoken? call your IUserService etc
    ShowViewModel<MainViewModel> ();
}

Since you're dismissing the facebook viewcontroller you'll find yourself back on the loginview momentarily before automatically navigating to the MainView

In your view project you need to ensure the plugin is loaded otherwise you'll receive an error during construction of the viewmodel, so in setup.cs

protected override void InitializeLastChance ()
{
    Cirrious.MvvmCross.Plugins.Messenger.PluginLoader.Instance.EnsureLoaded();

    base.InitializeLastChance ();
 }

Additionally you can also store the account credentials locally, this is described on the Xamarin.Auth link under AccountStore.Create().Save. Note that if you receive a platform not supported exception then add PLATFORM_IOS as a preprocessor directive to your project.

I realise the question is a couple of months old but since it rates high on google thought I'd provide an answer since there isn't any