Partager via


Se connecter avec Apple dans Xamarin.iOS

Connectez-vous avec Apple est un nouveau service qui fournit une protection d’identité pour les utilisateurs des services d’authentification tiers. À compter d’iOS 13, Apple exige que toute nouvelle application utilisant des services d’authentification tiers fournissent également la connexion avec Apple. Les applications existantes mises à jour n’ont pas besoin d’ajouter la connexion avec Apple jusqu’en avril 2020.

Ce document explique comment ajouter la connexion avec Apple aux applications iOS 13.

Configuration du développeur Apple

Avant de créer et d’exécuter une application à l’aide de la connexion avec Apple, vous devez effectuer ces étapes. Sur le portail Des certificats de développeur Apple, des identificateurs et des profils :

  1. Créez un identificateur d’ID d’application.
  2. Définissez une description dans le champ Description .
  3. Choisissez un ID de bundle explicite et définissez-le com.xamarin.AddingTheSignInWithAppleFlowToYourApp dans le champ.
  4. Activez la connexion avec la fonctionnalité Apple et inscrivez la nouvelle identité.
  5. Créez un profil d’approvisionnement avec la nouvelle identité.
  6. Téléchargez et installez-le sur votre appareil.
  7. Dans Visual Studio, activez la fonctionnalité Connexion avec Apple dans le fichier Entitlements.plist.

Vérifier l’état de connexion

Lorsque votre application commence, ou lorsque vous devez d’abord case activée l’état d’authentification d’un utilisateur, instanciez un ASAuthorizationAppleIdProvider et case activée l’état actuel :

var appleIdProvider = new ASAuthorizationAppleIdProvider ();
appleIdProvider.GetCredentialState (KeychainItem.CurrentUserIdentifier, (credentialState, error) => {
    switch (credentialState) {
    case ASAuthorizationAppleIdProviderCredentialState.Authorized:
        // The Apple ID credential is valid.
        break;
    case ASAuthorizationAppleIdProviderCredentialState.Revoked:
        // The Apple ID credential is revoked.
        break;
    case ASAuthorizationAppleIdProviderCredentialState.NotFound:
        // No credential was found, so show the sign-in UI.
        InvokeOnMainThread (() => {
            var storyboard = UIStoryboard.FromName ("Main", null);

            if (!(storyboard.InstantiateViewController (nameof (LoginViewController)) is LoginViewController viewController))
                return;

            viewController.ModalPresentationStyle = UIModalPresentationStyle.FormSheet;
            viewController.ModalInPresentation = true;
            Window?.RootViewController?.PresentViewController (viewController, true, null);
        });
        break;
    }
});

Dans ce code, appelé pendant FinishedLaunching le AppDelegate.cs, l’application gère lorsqu’un état est NotFound et présente l’utilisateur LoginViewController . Si l’état était retourné Authorized ou Revokedqu’une autre action peut être présentée à l’utilisateur.

LoginViewController pour la connexion avec Apple

Celui UIViewController qui implémente la logique de connexion et offre la connexion avec Apple doit implémenter IASAuthorizationControllerDelegate et IASAuthorizationControllerPresentationContextProviding comme dans l’exemple LoginViewController ci-dessous.

public partial class LoginViewController : UIViewController, IASAuthorizationControllerDelegate, IASAuthorizationControllerPresentationContextProviding {
    public LoginViewController (IntPtr handle) : base (handle)
    {
    }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
        // Perform any additional setup after loading the view, typically from a nib.

        SetupProviderLoginView ();
    }

    public override void ViewDidAppear (bool animated)
    {
        base.ViewDidAppear (animated);

        PerformExistingAccountSetupFlows ();
    }

    void SetupProviderLoginView ()
    {
        var authorizationButton = new ASAuthorizationAppleIdButton (ASAuthorizationAppleIdButtonType.Default, ASAuthorizationAppleIdButtonStyle.White);
        authorizationButton.TouchUpInside += HandleAuthorizationAppleIDButtonPress;
        loginProviderStackView.AddArrangedSubview (authorizationButton);
    }

    // Prompts the user if an existing iCloud Keychain credential or Apple ID credential is found.
    void PerformExistingAccountSetupFlows ()
    {
        // Prepare requests for both Apple ID and password providers.
        ASAuthorizationRequest [] requests = {
            new ASAuthorizationAppleIdProvider ().CreateRequest (),
            new ASAuthorizationPasswordProvider ().CreateRequest ()
        };

        // Create an authorization controller with the given requests.
        var authorizationController = new ASAuthorizationController (requests);
        authorizationController.Delegate = this;
        authorizationController.PresentationContextProvider = this;
        authorizationController.PerformRequests ();
    }

    private void HandleAuthorizationAppleIDButtonPress (object sender, EventArgs e)
    {
        var appleIdProvider = new ASAuthorizationAppleIdProvider ();
        var request = appleIdProvider.CreateRequest ();
        request.RequestedScopes = new [] { ASAuthorizationScope.Email, ASAuthorizationScope.FullName };

        var authorizationController = new ASAuthorizationController (new [] { request });
        authorizationController.Delegate = this;
        authorizationController.PresentationContextProvider = this;
        authorizationController.PerformRequests ();
    }
}

Animation de l’exemple d’application à l’aide de la connexion avec Apple

Cet exemple de code case activée l’état de connexion actuel et PerformExistingAccountSetupFlows se connecte à l’affichage actuel en tant que délégué. Si des informations d’identification de trousseau iCloud existantes ou des informations d’identification d’ID Apple sont trouvées, l’utilisateur est invité à l’utiliser.

Apple fournit ASAuthorizationAppleIdButton, un bouton spécifiquement à cet effet. Lorsqu’il est touché, le bouton déclenche le flux de travail géré dans la méthode HandleAuthorizationAppleIDButtonPress.

Gestion de l’autorisation

Dans l’implémentation IASAuthorizationController d’une logique personnalisée pour stocker le compte de l’utilisateur. L’exemple ci-dessous stocke le compte de l’utilisateur dans Keychain, le propre service de stockage d’Apple.

#region IASAuthorizationController Delegate

[Export ("authorizationController:didCompleteWithAuthorization:")]
public void DidComplete (ASAuthorizationController controller, ASAuthorization authorization)
{
    if (authorization.GetCredential<ASAuthorizationAppleIdCredential> () is ASAuthorizationAppleIdCredential appleIdCredential) {
        var userIdentifier = appleIdCredential.User;
        var fullName = appleIdCredential.FullName;
        var email = appleIdCredential.Email;

        // Create an account in your system.
        // For the purpose of this demo app, store the userIdentifier in the keychain.
        try {
            new KeychainItem ("com.example.apple-samplecode.juice", "userIdentifier").SaveItem (userIdentifier);
        } catch (Exception) {
            Console.WriteLine ("Unable to save userIdentifier to keychain.");
        }

        // For the purpose of this demo app, show the Apple ID credential information in the ResultViewController.
        if (!(PresentingViewController is ResultViewController viewController))
            return;

        InvokeOnMainThread (() => {
            viewController.UserIdentifierText = userIdentifier;
            viewController.GivenNameText = fullName?.GivenName ?? "";
            viewController.FamilyNameText = fullName?.FamilyName ?? "";
            viewController.EmailText = email ?? "";

            DismissViewController (true, null);
        });
    } else if (authorization.GetCredential<ASPasswordCredential> () is ASPasswordCredential passwordCredential) {
        // Sign in using an existing iCloud Keychain credential.
        var username = passwordCredential.User;
        var password = passwordCredential.Password;

        // For the purpose of this demo app, show the password credential as an alert.
        InvokeOnMainThread (() => {
            var message = $"The app has received your selected credential from the keychain. \n\n Username: {username}\n Password: {password}";
            var alertController = UIAlertController.Create ("Keychain Credential Received", message, UIAlertControllerStyle.Alert);
            alertController.AddAction (UIAlertAction.Create ("Dismiss", UIAlertActionStyle.Cancel, null));

            PresentViewController (alertController, true, null);
        });
    }
}

[Export ("authorizationController:didCompleteWithError:")]
public void DidComplete (ASAuthorizationController controller, NSError error)
{
    Console.WriteLine (error);
}

#endregion

Contrôleur d’autorisation

La dernière partie de cette implémentation est celle ASAuthorizationController qui gère les demandes d’autorisation pour le fournisseur.

#region IASAuthorizationControllerPresentation Context Providing

public UIWindow GetPresentationAnchor (ASAuthorizationController controller) => View.Window;

#endregion