Xamarin.iOS'ta Apple ile Oturum Açma

Download Sample Örneği indirme

Apple ile Oturum Açma, üçüncü taraf kimlik doğrulama hizmetlerinin kullanıcıları için kimlik koruması sağlayan yeni bir hizmettir. iOS 13'te başlayan Apple, üçüncü taraf kimlik doğrulama hizmetleri kullanan tüm yeni uygulamalar için Apple ile Oturum Açma olanağı sağlamasını gerektirir. Güncelleştirilmekte olan mevcut uygulamaların Nisan 2020'ye kadar Apple ile Oturum Aç'ı eklemesi gerekmez.

Bu belge, iOS 13 uygulamalarına Apple ile Oturum Açma'nın nasıl ekleneceğini açıklar.

Apple geliştirici kurulumu

Apple ile Oturum Aç'ı kullanarak bir uygulama derlemeden ve çalıştırmadan önce bu adımları tamamlamanız gerekir. Apple Geliştirici Sertifikaları, Tanımlayıcılar ve Profiller portalında:

  1. Yeni bir Uygulama Kimlikleri Tanımlayıcısı oluşturun.
  2. Açıklama alanında bir açıklama ayarlayın.
  3. Açık Bir Paket Kimliği seçin ve alanında ayarlayıncom.xamarin.AddingTheSignInWithAppleFlowToYourApp.
  4. Apple ile Oturum Aç özelliğini etkinleştirin ve yeni Kimliği kaydedin.
  5. Yeni Kimlik ile yeni bir Sağlama Profili oluşturun.
  6. Cihazınıza indirip yükleyin.
  7. Visual Studio'da, Entitlements.plist dosyasında Apple ile Oturum Aç özelliğini etkinleştirin.

Oturum açma durumunu denetleme

Uygulamanız başladığında veya bir kullanıcının kimlik doğrulama durumunu ilk kez denetlemeniz gerektiğinde, örneğini ASAuthorizationAppleIdProvider oluşturun ve geçerli durumu denetleyin:

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

içinde sırasında FinishedLaunching çağrılan bu kodda AppDelegate.cs, bir durum olduğunda NotFound uygulama bunu işler ve kullanıcıya sunar LoginViewController . Durum veya döndürmüştüyse AuthorizedRevoked, kullanıcıya farklı bir eylem sunulabilir.

Apple ile Oturum Açmak için LoginViewController

UIViewController Oturum açma mantığını uygulayan ve Aşağıdaki örnekte olduğu gibi Apple ile Oturum Açma'nın LoginViewController uygulanması IASAuthorizationControllerDelegateIASAuthorizationControllerPresentationContextProviding gerekir.

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

Bu örnek kod, içinde PerformExistingAccountSetupFlows geçerli oturum açma durumunu denetler ve geçerli görünüme temsilci olarak bağlanır. Mevcut bir iCloud Anahtar Zinciri kimlik bilgisi veya Apple Kimliği kimlik bilgisi bulunursa, kullanıcıdan bunu kullanması istenir.

Apple, bu amaca özel olarak bir düğme sağlar ASAuthorizationAppleIdButton. Dokunulduğunda, düğme yönteminde HandleAuthorizationAppleIDButtonPressişlenen iş akışını tetikler.

Yetkilendirmeyi işleme

IASAuthorizationController içinde, kullanıcının hesabını depolamak için herhangi bir özel mantık uygulayın. Aşağıdaki örnekte kullanıcının hesabı Apple'ın kendi depolama hizmeti olan Anahtarlık'ta depolanmıştır.

#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

Yetkilendirme Denetleyicisi

Bu uygulamanın son parçası, sağlayıcı için yetkilendirme isteklerini yöneten parçadır ASAuthorizationController .

#region IASAuthorizationControllerPresentation Context Providing

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

#endregion