Přihlášení pomocí Apple v Xamarin.iOS

Download Sample Stažení ukázky

Přihlášení pomocí Společnosti Apple je nová služba, která poskytuje ochranu identit uživatelům ověřovacích služeb třetích stran. Počínaje iOSem 13 vyžaduje Apple, aby všechny nové aplikace používající ověřovací služby třetích stran měly také poskytovat Přihlášení pomocí Společnosti Apple. Stávající aplikace, které se aktualizují, nemusí do dubna 2020 přidávat přihlášení k Apple.

V tomto dokumentu se dozvíte, jak do aplikací pro iOS 13 přidat přihlášení pomocí Apple.

Nastavení vývojáře Apple

Před sestavením a spuštěním aplikace pomocí funkce Přihlásit se s Apple je potřeba provést tyto kroky. Na portálu Certifikáty pro vývojáře Apple, identifikátory a profily :

  1. Vytvořte nový identifikátor ID aplikace.
  2. Nastavte popis v poli Popis .
  3. Zvolte ID explicitního balíčku a nastavte com.xamarin.AddingTheSignInWithAppleFlowToYourApp ho v poli.
  4. Povolte přihlášení pomocí funkce Apple a zaregistrujte novou identitu.
  5. Vytvořte nový zřizovací profil s novou identitou.
  6. Stáhněte a nainstalujte ho do zařízení.
  7. V sadě Visual Studio povolte přihlášení pomocí funkce Apple v souboru Entitlements.plist .

Kontrola stavu přihlášení

Když začne aplikace nebo když potřebujete nejprve zkontrolovat stav ověřování uživatele, vytvořte instanci a zkontrolujte ASAuthorizationAppleIdProvider aktuální stav:

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;
    }
});

V tomto kódu, který se volá během FinishedLaunching aplikace AppDelegate.cs, bude zpracovávat, když je NotFound stav a prezentovat LoginViewController uživateli. Pokud se stav vrátil Authorized , nebo Revokedse uživateli může předložit jiná akce.

A LoginViewController for Sign In with Apple

To UIViewController implementuje logiku přihlášení a nabízí Přihlášení s Apple musí implementovat IASAuthorizationControllerDelegate a IASAuthorizationControllerPresentationContextProviding jako v následujícím příkladu LoginViewController .

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 of sample app using Sign In with Apple

Tento ukázkový kód zkontroluje aktuální stav PerformExistingAccountSetupFlows přihlášení a připojí se k aktuálnímu zobrazení jako delegát. Pokud se najde existující přihlašovací údaje klíčenky iCloudu nebo přihlašovací údaje Apple ID, zobrazí se uživateli výzva k jeho použití.

Apple poskytuje ASAuthorizationAppleIdButtontlačítko speciálně pro tento účel. Když se dotknete, tlačítko aktivuje pracovní postup zpracovaný v metodě HandleAuthorizationAppleIDButtonPress.

Zpracování autorizace

V implementaci IASAuthorizationController jakékoli vlastní logiky pro uložení účtu uživatele. Následující příklad ukládá uživatelský účet do řetězce klíčů, který je vlastní službou úložiště 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

Autorizační kontroler

Poslední součástí této implementace je ASAuthorizationController správa žádostí o autorizaci pro poskytovatele.

#region IASAuthorizationControllerPresentation Context Providing

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

#endregion