doc/articles/interop/apple-login.md
In Uno Platform projects, implementing a "Sign in with Apple" Button is possible through MAUI embedding (more on which in our Overview). Below is a simple example of how you can add the Apple Sign-In Button to your project. We will inject it into the visual tree from the code-behind and handle the authorization using Apple's Authentication Services.
Activate the Apple Sign-In Capability:
Entitlements.plist file and locate the "Sign In With Apple" checkbox. After checking it, ensure you save your changes.Entitlements.plist file in any text editor and add the following within the <dict> tag:<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
</array>
Import Necessary Namespaces:
using AuthenticationServices;
using Foundation;
using UIKit;
In the constructor of your Page or control, create the Apple Sign-In Button:
[!Important] Ensure that you wrap platform-specific code in
#if __IOS__directives. For more details, refer to the Platform-specific C# documentation.
var appleSignInButton = new ASAuthorizationAppleIdButton(ASAuthorizationAppleIdButtonType.Default, ASAuthorizationAppleIdButtonStyle.WhiteOutline);
appleSignInButton.TouchUpInside += HandleAuthorizationAppleIDButtonPress;
appleSignInButton.CornerRadius = 50;
// Retain the delegate to prevent garbage collection
_appleSignInDelegate = new AuthorizationControllerDelegate(this);
[!NOTE] It's important to retain a reference to the delegate (
_appleSignInDelegate) to avoid garbage collection issues. This ensures that the authorization process is completed without interruption.
Inject the Apple Sign-In button into the visual tree using VisualTreeHelper.AdaptNative:
var adaptedAppleButton = VisualTreeHelper.AdaptNative(appleSignInButton);
var borderWrapper = new Border
{
MinHeight = 50,
MinWidth = 250,
HorizontalAlignment = HorizontalAlignment.Center,
Child = adaptedAppleButton,
};
m_MainStackPanel.Children.Add(borderWrapper);
Handle the button's TouchUpInside event to initiate Apple Sign-In:
private void HandleAuthorizationAppleIDButtonPress(object sender, EventArgs e)
{
var appleIDProvider = new ASAuthorizationAppleIdProvider();
var request = appleIDProvider.CreateRequest();
request.RequestedScopes = new[] { ASAuthorizationScope.FullName, ASAuthorizationScope.Email };
var authorizationController = new ASAuthorizationController(new ASAuthorizationRequest[] { request });
authorizationController.Delegate = _appleSignInDelegate; // Use the retained delegate
authorizationController.PresentationContextProvider = new PresentationContextProvider(); // Set the presentation context provider
authorizationController.PerformRequests();
}
To handle the result of the sign-in process, create a custom delegate:
public class AuthorizationControllerDelegate : ASAuthorizationControllerDelegate
{
private readonly MyUserControl _parent;
public AuthorizationControllerDelegate(MyUserControl parent)
{
_parent = parent;
}
public override void DidComplete(ASAuthorizationController controller, ASAuthorization authorization)
{
System.Diagnostics.Debug.WriteLine("Authorization successful.");
try
{
var appleIdCredential = authorization.GetCredential<ASAuthorizationAppleIdCredential>();
var userIdentifier = appleIdCredential?.User;
// Handle successful authorization, retrieve user details
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Authorization failed: {ex.Message}");
}
}
}
If you're using an MVVM architecture, the delegate should handle sign-in logic indirectly by passing the necessary data to the ViewModel. This keeps the code clean and follows MVVM principles. For example:
MyUserControl) to the AuthorizationControllerDelegate, pass a reference to the ViewModel or a dedicated service.Example:
public class AuthorizationControllerDelegate : ASAuthorizationControllerDelegate
{
private readonly MyViewModel _viewModel;
public AuthorizationControllerDelegate(MyViewModel viewModel)
{
_viewModel = viewModel;
}
public override void DidComplete(ASAuthorizationController controller, ASAuthorization authorization)
{
System.Diagnostics.Debug.WriteLine("Authorization successful.");
try
{
var appleIdCredential = authorization.GetCredential<ASAuthorizationAppleIdCredential>();
var userIdentifier = appleIdCredential?.User;
// Pass the user info to the ViewModel for further processing
_viewModel.HandleSuccessfulAuthorization(userIdentifier);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Authorization failed: {ex.Message}");
}
}
}
For proper handling of the presentation context on iOS, implement a PresentationContextProvider:
public class PresentationContextProvider : NSObject, IASAuthorizationControllerPresentationContextProviding
{
public UIWindow GetPresentationAnchor(ASAuthorizationController controller)
{
return UIApplication.SharedApplication.KeyWindow;
}
}
For more details on platform-specific considerations or to improve the user experience: