web-dev-qa-db-fra.com

Comment se connecter à Facebook dans Xamarin.Forms

Je souhaite réaliser un projet Xamarin.Forms, ciblant iOS, Android et Windows Phone.).

Mon application doit authentifier les utilisateurs via Facebook.

Devrais-je implémenter la connexion pour chaque plate-forme indépendamment ou utiliser un flux manuel? https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/v2.

Je préfère avoir une seule implémentation du flux de connexion et l'utiliser sur toutes les plateformes.

Comment puis-je obtenir une seule implémentation du flux de connexion Facebook?

45
Morten Lyhr

Vous pouvez consommer soit Xamarin.Social ou Xamarin.Auth pour cela. Cela permet d'utiliser le même api quelle que soit la plateforme.

Pour le moment, ces bibliothèques ne sont pas encore PCL, mais vous pouvez toujours les utiliser à partir d'un projet d'actifs partagés, ou résumer l'API dont vous avez besoin dans une interface et injecter avec DependencyService ou tout autre conteneur DI.

20

UPDATE (24/10/17): Bien que cette façon de faire fonctionnait bien il y a quelques années, je préconise maintenant fortement l'utilisation de l'interface utilisateur native pour le faire. authentification, par opposition à la méthode webview illustrée ici. Auth0 est un excellent moyen d’effectuer la connexion à l’UI native pour vos applications, en utilisant un grand nombre de fournisseurs d’identité: https://auth0.com/docs/quickstart/native/xamarin

EDIT: J'ai finalement mis un exemple pour cela sur Gihub

J'ai posté une réponse sur les forums Xamarin. Je vais la répéter ici.

Commençons par le cœur de l'application, le projet Xamarin.Forms PCL . Votre classe App ressemblera à ceci:

namespace OAuth2Demo.XForms
{
    public class App
    {
        static NavigationPage _NavPage;

        public static Page GetMainPage ()
        {
            var profilePage = new ProfilePage();

            _NavPage = new NavigationPage(profilePage);

            return _NavPage;
        }

        public static bool IsLoggedIn {
            get { return !string.IsNullOrWhiteSpace(_Token); }
        }

        static string _Token;
        public static string Token {
            get { return _Token; }
        }

        public static void SaveToken(string token)
        {
            _Token = token;
        }

        public static Action SuccessfulLoginAction
        {
            get {
                return new Action (() => {
                    _NavPage.Navigation.PopModalAsync();
                });
            }
        }
    }
}

La première chose à noter est la méthode GetMainPage(). Cela indique à l’application quel écran elle doit charger en premier au lancement.

Nous avons également une propriété et une méthode simples pour stocker le Token renvoyé par le service d’authentification, ainsi qu’une simple propriété IsLoggedIn.

Il y a aussi une propriété Action; quelque chose que j’ai bloqué ici afin de permettre aux implémentations de plate-forme d’effectuer une action de navigation Xamarin.Forms. Plus sur cela plus tard.

Vous remarquerez également un peu de rouge dans votre IDE car nous n'avons pas encore créé la classe ProfilePage. Alors faisons-le.

Créez une classe ProfilePage très simple dans le projet Xamarin.Forms PCL . Nous n'allons même pas en faire quelque chose d'extraordinaire car cela dépendra de vos besoins particuliers. Par souci de simplicité, dans cet exemple, il ne comportera qu'une seule étiquette:

namespace OAuth2Demo.XForms
{
    public class ProfilePage : BaseContentPage
    {
        public ProfilePage ()
        {
            Content = new Label () {
                Text = "Profile Page", 
                VerticalOptions = LayoutOptions.CenterAndExpand,
                HorizontalOptions = LayoutOptions.CenterAndExpand, 
            };
        }
    }
}

Encore une fois, vous aurez probablement du rouge dans votre IDE car il semble manquer la classe BaseContentPage. Le seul but de la classe BaseContentPage est de s'assurer qu'aucun écran de l'application ne peut être affiché tant que l'utilisateur n'est pas connecté. (Dans cette démo simplifiée, nous ne faisons que persister la les informations utilisateur dans la mémoire, vous devrez donc vous reconnecter chaque fois que l'application est exécutée. Dans une application réelle, vous stockeriez les informations utilisateur authentifiées dans le trousseau de l'appareil, ce qui vous éviterait d'avoir à vous connecter à chaque application démarre.)

Créez une classe BaseContentPage dans le projet Xamarin.Forms PCL :

namespace OAuth2Demo.XForms
{
    public class BaseContentPage : ContentPage
    {
        protected override void OnAppearing ()
        {
            base.OnAppearing ();

            if (!App.IsLoggedIn) {
                Navigation.PushModalAsync(new LoginPage());
            }
        }
    }
}

Il y a quelques choses intéressantes qui se passent ici:

  1. Nous substituons la méthode OnAppearing(), qui est similaire à la méthode ViewWillAppear dans un UIViewController iOS. Vous pouvez exécuter ici tout code que vous souhaitez exécuter juste avant que l'écran n'apparaisse.

  2. La seule chose que nous faisons dans cette méthode est de vérifier si l'utilisateur est connecté. Si ce n'est pas le cas, nous effectuons un push modal à une classe appelée LoginPage. Si vous n'êtes pas familier avec le concept de modal, c'est simplement une vue qui éloigne l'utilisateur du flux normal d'applications pour pouvoir effectuer une tâche spéciale. dans notre cas, pour effectuer une connexion.

Créons donc la classe LoginPage dans le projet Xamarin.Forms PCL :

namespace OAuth2Demo.XForms
{
    public class LoginPage : ContentPage
    {

    }
}

Attends ... pourquoi cette classe n'a-t-elle pas un corps ???

Étant donné que nous utilisons le composant Xamatin.Auth (qui permet de créer et de présenter une vue Web qui fonctionne avec les informations OAuth2 fournies), nous ne souhaitons aucune implémentation dans notre classe LoginPage. . Je sais que cela semble étrange, mais supporte-moi.

Le LoginPageRenderer pour iOS

Jusqu'à présent, nous travaillions uniquement dans le projet Xamarin.Forms PCL . Mais maintenant, nous devons fournir l'implémentation spécifique à la plate-forme de notre LoginPage dans le projet iOS. C’est là que le concept de Renderer entre en jeu.

Dans Xamarin.Forms, lorsque vous souhaitez fournir des écrans et des contrôles spécifiques à la plate-forme (c'est-à-dire des écrans dont le contenu ne provient pas des pages de résumé du projet PCL Xamarin.Forms), vous le faites avec Rendeurs .

Créez une classe LoginPageRenderer dans votre projet de plate-forme iOS :

[Assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))]

namespace OAuth2Demo.XForms.iOS
{
    public class LoginPageRenderer : PageRenderer
    {
        public override void ViewDidAppear (bool animated)
        {
            base.ViewDidAppear (animated);

            var auth = new OAuth2Authenticator (
                clientId: "", // your OAuth2 client id
                scope: "", // the scopes for the particular API you're accessing, delimited by "+" symbols
                authorizeUrl: new Uri (""), // the auth URL for the service
                redirectUrl: new Uri ("")); // the redirect URL for the service

            auth.Completed += (sender, eventArgs) => {
            // We presented the UI, so it's up to us to dimiss it on iOS.
            App.SuccessfulLoginAction.Invoke();

            if (eventArgs.IsAuthenticated) {
                // Use eventArgs.Account to do wonderful things
                App.SaveToken(eventArgs.Account.Properties["access_token"]);
            } else {
                // The user cancelled
            }
        };

        PresentViewController (auth.GetUI (), true, null);
            }
        }
    }
}

Il y a des choses importantes à noter:

  1. La ligne [Assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))] en haut (et surtout avant la déclaration de l'espace de noms) utilise Xamarin.Forms DependencyService . Ce n'est pas la plus belle chose au monde parce que ce n'est pas IoC/DI, mais peu importe ... ça marche. C'est le mécanisme qui "mappe" notre LoginPageRenderer au LoginPage.

  2. C’est la classe dans laquelle nous utilisons réellement le composant Xamarin.Auth. C'est de là que vient la référence OAuth2Authenticator.

  3. Une fois que la connexion est réussie, nous lançons une navigation Xamarin.Forms via App.SuccessfulLoginAction.Invoke();. Cela nous ramène à la ProfilePage.

  4. Puisque nous sommes sur iOS, nous utilisons toute notre logique de la méthode ViewDidAppear().

Le LoginPageRenderer pour Android

Créez une classe LoginPageRenderer dans votre projet de plate-forme Android . (Notez que le nom de la classe que vous créez est identique à celui du projet iOS, mais ici, dans le projet Android, le créateur de page hérite des classes Android au lieu des classes iOS. .)

[Assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))]

namespace OAuth2Demo.XForms.Android
{
    public class LoginPageRenderer : PageRenderer
    {
        protected override void OnModelChanged (VisualElement oldModel, VisualElement newModel)
        {
            base.OnModelChanged (oldModel, newModel);

            // this is a ViewGroup - so should be able to load an AXML file and FindView<>
            var activity = this.Context as Activity;

            var auth = new OAuth2Authenticator (
                clientId: "", // your OAuth2 client id
                scope: "", // the scopes for the particular API you're accessing, delimited by "+" symbols
                authorizeUrl: new Uri (""), // the auth URL for the service
                redirectUrl: new Uri ("")); // the redirect URL for the service

            auth.Completed += (sender, eventArgs) => {
            if (eventArgs.IsAuthenticated) {
                App.SuccessfulLoginAction.Invoke();
                // Use eventArgs.Account to do wonderful things
                App.SaveToken(eventArgs.Account.Properties["access_token"]);
            } else {
                // The user cancelled
            }
        };

        activity.StartActivity (auth.GetUI(activity));
        }
    }
}

Encore une fois, jetons un coup d'oeil à quelques choses intéressantes:

  1. La ligne [Assembly: ExportRenderer (typeof (LoginPage), typeof (LoginPageRenderer))] en haut (et surtout avant la déclaration de l'espace de noms) utilise Xamarin.Forms DependencyService . Aucune différence ici de la version iOS de LoginPageRenderer.

  2. Là encore, nous utilisons actuellement le composant Xamarin.Auth. C'est de là que vient la référence OAuth2Authenticator.

  3. Comme avec la version iOS, une fois la connexion réussie, nous lançons une navigation Xamarin.Forms via App.SuccessfulLoginAction.Invoke();. Cela nous ramène à la ProfilePage.

  4. Contrairement à la version iOS, nous utilisons toute la logique à l'intérieur de la méthode OnModelChanged() à la place de ViewDidAppear().

La voici sur iOS:

Xamarin.Auth with Xamarin.Forms iOS example

... et Android:

Xamarin.Auth with Xamarin.Forms Android example

UPDATE: J'ai également fourni un exemple détaillé sur mon blog: http://www.joesauve.com/using-xamarin- auth-with-xamarin-forms /

102
NovaJoe

J'ai créé un exemple de projet pour montrer comment créer un identifiant Facebook à l'aide d'un composant Facebook natif, et non via une vue Web telle que celle proposée ici. Vous pouvez le vérifier à cette adresse:

https://github.com/IdoTene/XamarinFormsNativeFacebook

9
IdoT

IOS 8: Pour ceux qui utilisent le code @NovaJoe et sont bloqués dans l'affichage, ajoutez le code ci-dessous à la solution de contournement:

 bool hasShown;

    public override void ViewDidAppear(bool animated)
    {
        if (!hasShown)
        {
            hasShown = true;

            // the rest of @novaJoe code
        }

    }
5
Alexandre

Voici un bon exemple d'authentification Xamarin.Forms. La documentation dans le code est Nice. Il utilise une vue Web pour afficher l'écran de connexion, mais vous pouvez sélectionner le type de connexion souhaité. Il enregistre également un jeton utilisateur afin qu'il ne soit pas obligé de se reconnecter.

https://github.com/rlingineni/Xamarin.Forms_Authentication

3
MangoBoy

Un autre ajout au code de @ NovaJoe, sur iOS8 avec Facebook, vous devez modifier la classe Renderer comme indiqué ci-dessous pour fermer la vue après une authentification réussie.

auth.Completed += (sender, eventArgs) => {
            // We presented the UI, so it's up to us to dimiss it on iOS.

/ * Importand pour ajouter cette ligne * /

            DismissViewController (true, null);

/ * * /

            if (eventArgs.IsAuthenticated) {
                App.Instance.SuccessfulLoginAction.Invoke ();

                // Use eventArgs.Account to do wonderful things
                App.Instance.SaveToken (eventArgs.Account.Properties ["access_token"]);


            } else {
                // The user cancelled
            }
        };
0
Illuminati

L'implémentation correcte pour Androids PageRenderer est:

using System;
using Android.App;
using Android.Content;
using OAuth2Demo.XForms.Android;
using Xamarin.Auth;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using XamarinAuth;

[Assembly: ExportRenderer(typeof(LoginPage), typeof(LoginPageRenderer))]

namespace OAuth2Demo.XForms.Android
{
    public class LoginPageRenderer : PageRenderer
    {
        public LoginPageRenderer(Context context) : base(context) { }

        protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
        {
            base.OnElementChanged(e);

            // this is a ViewGroup - so should be able to load an AXML file and FindView<>
            var activity = this.Context as Activity;

            var auth = new OAuth2Authenticator(
                clientId: "<Constants.clientId>", // your OAuth2 client id
                scope: "<Constants.scope>", // the scopes for the particular API you're accessing, delimited by "+" symbols
                authorizeUrl: new Uri("<Constants.authorizeUrl>"), // the auth URL for the service
                redirectUrl: new Uri("<Constants.redirectUrl>")); // the redirect URL for the service

            auth.Completed += (sender, eventArgs) =>
            {
                if (eventArgs.IsAuthenticated)
                {
                    App.SuccessfulLoginAction.Invoke();
                    // Use eventArgs.Account to do wonderful things
                    App.SaveToken(eventArgs.Account.Properties["access_token"]);
                }
                else
                {
                    // The user cancelled
                }
            };

            activity.StartActivity(auth.GetUI(activity));
        }
    }
}
0
Janis Thr