The sample code

Log in through Apple for user authentication

Provide a way for app users to set up an account and start using the service.

Download the official sample code

Add the “Log in through Apple” button

The Apple login button comes in two ways

1. “Log in via Apple” button (ASAuthorizationAppleIDButton (English)). The view controller also adds itself as the target of the button and passes the action to invoke when the button receives a touch event

func setupProviderLoginView() {
    let authorizationButton = ASAuthorizationAppleIDButton()
    authorizationButton.addTarget(self, action: #selector(handleAuthorizationAppleIDButtonPress), for: .touchUpInside)
    self.view.addSubview(authorizationButton)
}
Copy the code

Important information

In add “by Apple login” button to the Storyboard, you must also Identity in Xcode Inspector in the control class value is set to ASAuthorizationAppleIDButton.

2. Customize the Apple login button style

Please refer to the (Apple login button design specification)

Request authorization using the Apple ID

When users click “by Apple login” button, the view controller will be called handleAuthorizationAppleIDButtonPress () function, the function executes authorization request to obtain the user’s full name and email address, so as to start the certification process. The system then checks to see if the user is logged in with an Apple ID on the device. If the user is not logged in at the system level, the app will display a reminder directing the user to log in with their Apple ID in Settings.

@objc func handleAuthorizationAppleIDButtonPress() {
    let appleIDProvider = ASAuthorizationAppleIDProvider()
    let request = appleIDProvider.createRequest()
    request.requestedScopes = [.fullName, .email]
    
    let authorizationController = ASAuthorizationController(authorizationRequests: [request])
    authorizationController.delegate = self
    authorizationController.presentationContextProvider = self
    authorizationController.performRequests()
}
Copy the code

Important information

Users must enable two-factor authentication to use Log in through Apple, which ensures that access to their accounts is secure.

The authorization controller calls the presentationAnchor(for:)(English) function to get a window from the app for presenting the “log in via Apple” content to the user as a modal form.

func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
    return self.view.window!
}
Copy the code

If the user is already logged in at the system level with an Apple ID, this form is displayed to introduce the “Log in through Apple” feature, and then another form is displayed to allow the user to edit the information in the account. Users can edit their first and last names, select another email address as their contact information, and hide their email address from the app. If the user chooses to hide their email address from the app, Apple generates a proxy email address to forward the email to the user’s private email address. Finally, the user enters the password for the Apple ID and then clicks “Continue” to create the account.

Handling user credentials

If successful authentication, authorization controller will be called authorizationController (controller: didCompleteWithAuthorization:) (English) entrust function, app to use this function to the user’s data stored in the key string.

func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { switch authorization.credential { case let appleIDCredential as ASAuthorizationAppleIDCredential: // Create an account in your system. let userIdentifier = appleIDCredential.user let fullName = appleIDCredential.fullName let email = appleIDCredential.email // For the purpose of this demo app, store the `userIdentifier` in the keychain. self.saveUserInKeychain(userIdentifier) // For the purpose of this demo app,  show the Apple ID credential information in the `ResultViewController`. self.showResultViewController(userIdentifier: userIdentifier, fullName: fullName, email: email) case let passwordCredential as ASPasswordCredential: // Sign in using an existing iCloud Keychain credential. let username = passwordCredential.user let password = passwordCredential.password // For the purpose of this demo app, show the password credential as an alert. DispatchQueue.main.async { self.showPasswordCredentialAlert(username: username, password: password) } default: break } }Copy the code

annotation

In your implementation, ASAuthorizationControllerDelegate.authorizationController(controller:didCompleteWithAuthorization:) The delegate function should use the data contained in the user identifier to create an account in your system.

If authentication fails, the authorization controller will be called authorizationController (controller: didCompleteWithError:) (English) entrust function to handle errors.

func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
    // Handle error.
}
Copy the code

After the system authenticates the user, the App displays the ResultViewController, which displays the user information requested from the framework, including the full name and email address provided by the user. The view controller also displays a “Sign Out” button and stores user data in a keychain. When the user taps the “Sign Out” button, the app removes the user’s information from the view controller and key chain and displays the LoginViewController to the user.

Request existing credentials

LoginViewController. PerformExistingAccountSetupFlows () function will pass the request Apple ID and ripped the key string of passwords to check whether the user is existing accounts. With handleAuthorizationAppleIDButtonPress (), authorized controller can set its display content providers, and entrusted to LoginViewController object.

func performExistingAccountSetupFlows() {
    // Prepare requests for both Apple ID and password providers.
    let requests = [ASAuthorizationAppleIDProvider().createRequest(),
                    ASAuthorizationPasswordProvider().createRequest()]
    
    // Create an authorization controller with the given requests.
    let authorizationController = ASAuthorizationController(authorizationRequests: requests)
    authorizationController.delegate = self
    authorizationController.presentationContextProvider = self
    authorizationController.performRequests()
}
Copy the code

AuthorizationController (controller: didCompleteWithAuthorization:) entrust function will check credentials are Apple ID (ASAuthorizationAppleIDCredential (English) or password credentials (ASPasswordCredential (English)). If it is a password credential, an alert is displayed allowing the user to authenticate with an existing account.

Check user credentials at startup

The sample app displays the “Log in through Apple” user interface only when necessary. App will entrust in the App starts immediately by appDelegate. Application (_ : didFinishLaunchingWithOptions:) function to check the status of a stored user credentials.

The getCredentialState(forUserID: Completion 🙂 function retrieves the state of the user identifier stored in the key string. If the user has authorized the app (for example, if the user has logged in to the app on the device with an Apple ID), the app continues to execute. If the user revokes authorization for the app, or if the app cannot find the user’s credential status, the app displays the login form by calling the showLoginViewController() function.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let appleIDProvider = ASAuthorizationAppleIDProvider() appleIDProvider.getCredentialState(forUserID: KeychainItem.currentUserIdentifier) { (credentialState, error) in switch credentialState { case .authorized: break // The Apple ID credential is valid. case .revoked, .notFound: // The Apple ID credential is either revoked or was not found, so show the sign-in UI. DispatchQueue.main.async { self.window? .rootViewController? .showLoginViewController() } default: break } } return true }Copy the code

PS:

The user can obtain the userID of the user every time he logs in

Only when a user logs in for the first time can the user be authorized to obtain user information based on the user’s choice

You can obtain the user’s first or last name (the user must give at least one of them) and email address (the user can choose to hide it)

From the mobile phone -> Settings -> Click your profile picture to enter password and Security -> App using Apple ID -> Select App -> Stop using Apple ID to update the app’s Apple ID login to the first login