How to Integrate Sign In with Apple in your Application?
In iOS 13 at WWDC 2019, Apple introduces a fast, easy way to sign in to apps and websites i.e. Sign In with Apple.
- In WWDC 2019 with iOS 13, iPadOS 13, WatchOS 6, tvOS 13, and macOS Catalina, Apple introduced the “Sign In With Apple” solution.
- As per the WWDC 2019 announcement, If your App offers any third party sign-on system(SOS) then It must have to offer “Sign In With Apple” as an option, otherwise, you will have to face app store rejection.
- You can have “Sign in with Apple” anyway in your app if you don’t have any such 3rd party login.
Steps to integrate ‘Sign in with Apple’
Step 1: Configure Project at Apple Developer Portal
Set up an Apple account at the Apple developer portal to add “Sign In with Apple” and generate your provisioning profile.
Create a new project and set the development team and provisioning profile in the Signing & Capabilities.
If you’ve already created a project and provisioning profile then ignore the above two points.
Add the “Sign In with Apple” capability in your project. This will add an entitlement that lets your app use Sign In with Apple.
Step 2: Configure Project in Xcode
Open your Xcode Project.
- Project Navigator→ Select Project → Select Target.
- In Project Editor, Click Signing & Capabilities.
- Add Capability by clicking the + button. Search for Sign In with Apple Capability in Capability Library.
- Double-click the capability to add.
Step 3: Add Apple LogIn ButtonAuthenticationServices
framework provides ASAuthorizationAppleIDButton
to enable users to initiate the “Sign In with Apple”. Then create an instance of ASAuthorizationAppleIDButton
and add a target for touchUpInside
action. After that, you can add this button in your view.
func addAppleLogInButton() {
if #available(iOS 13.0, *) {
let authorizationButton = ASAuthorizationAppleIDButton()
authorizationButton.addTarget(self, action: #selector(tapBtnAppleLogin(_:)), for: .touchUpInside) //Add button on some view or stack
self.viewAppleLogin.addSubview(authorizationButton) // Setup Layout Constraints to be in the center of the screen
authorizationButton.translatesAutoresizingMaskIntoConstraints = falseNSLayoutConstraint.activate([authorizationButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
authorizationButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),
authorizationButton.widthAnchor.constraint(equalToConstant: 228),
authorizationButton.heightAnchor.constraint(equalToConstant: 49)]) }
}
Important:
When adding the “Sign in with Apple” button to your storyboard, you must also set the control’s class value to ASAuthorizationAppleIDButton
in Xcode’s Identity Inspector.
Step 4: Handle “Sign in with Apple” Button Press
Now on the press of “Sign In with Apple” Button, we need to use a provider (ASAuthorizationAppleIDProvider
) to create a request (ASAuthorizationAppleIDRequest
), which we then use to initialize a controller (ASAuthorizationController
) that performs the request. We can use one or more of ASAuthorization.Scope
values in the requestedScopes
array to request certain contact information from the user.
@objc private func handleLogInWithAppleIDButtonPress() {
let appleIDProvider = ASAuthorizationAppleIDProvider()
let request = appleIDProvider.createRequest()
request.requestedScopes = [.fullName, .email]
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
authorizationController.delegate = self
authorizationController.presentationContextProvider = self
authorizationController.performRequests()
}
Step 5: Existing Account Setup Flow
There is a huge possibility of a user might already be logged in with your application. For that, we need to use both ASAuthorizationAppleIDProvider
and ASAuthorizationPasswordProvider
provider to create the request, which we then use to initialize a controller (ASAuthorizationController
) that performs the request.
ASAuthorizationPasswordProvider
is a mechanism for generating requests to authenticate users based on their Apple IDASAuthorizationPasswordProvider
is a mechanism for generating requests to perform keychain credential sharing.
As we only get user Name and Email first time in the app and when we authenticate it another time we only get an identifier. To preserve the user data we are saving it in the Keychain so that we can use this data even later to save on server or access it later.
private func performExistingAccountSetupFlows() {
let requests = [ASAuthorizationAppleIDProvider().createRequest(), ASAuthorizationPasswordProvider().createRequest()]
let authorizationController = ASAuthorizationController(authorizationRequests: requests)
authorizationController.delegate = self
authorizationController.presentationContextProvider = self
authorizationController.performRequests()
}
We can call this function from the LoginViewController viewDidLoad:
.
Step 6: Handle ASAuthorizationController Delegate and Presentation Context
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
//Handle error here
}func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
// Create an account in your system.
let userIdentifier = appleIDCredential.user
let userFirstName = appleIDCredential.fullName?.givenName
let userLastName = appleIDCredential.fullName?.familyName
let userEmail = appleIDCredential.email //Save all user information in the keychain.
} else if let passwordCredential = authorization.credential as? ASPasswordCredential {
// Sign in using an existing iCloud Keychain credential.
let username = passwordCredential.user
let password = passwordCredential.password
//Navigate to other view controller
}
}func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return self.view.window!
}
presentationAnchor(controller:) Tells the delegate from which window it should present content to the user.
Step 7: Check Credential State
We can use that userIdentifier which we got from ASAuthorizationAppleIDCredential
object in the last step to check the user credential state. We can get credential state for an userIdentifier by calling the getCredentialState(forUserID: completion:) method:
let appleIDProvider = ASAuthorizationAppleIDProvider()
appleIDProvider.getCredentialState(forUserID: userIdentifier) { (credentialState, error) in
switch credentialState {
case .authorized:
// The Apple ID credential is valid. Show Home UI Here
break
case .revoked:
// The Apple ID credential is revoked. Show SignIn UI Here.
break
case .notFound:
// No credential was found. Show SignIn UI Here.
break
default:
break
}
}
Step 8: Create an Auth Key with Sign In with Apple
To enable Sign In with Apple in your developer account you need to create an Auth Key with Sign In with Apple.
Go to the “Certificates, Identifiers & Profile” section and then click on the “Keys” option.
Click on the “Create a key” option. Enter the name of the key and enable the “Sign in with Apple” option
Now Configure key and click on “Save”
Now click on “Register” and its done.
Step 9: Reset an Existing Account
If you need to reset an existing account to test the first Sign In experience again then open the Settings app of your iOS device, tap your account in the Apple ID header, proceed to Password & security. Find your application under Applications using your Apple ID and swipe to delete it.
Step 10: (Optional) Add Domain and e-mail to contact your users
As ‘Sign in with Apple‘ gives the users the option to hide their email address when they login.
To be able to contact those users, you need to set up a domain and a contact email in your Apple Developer Account.
Choose More from left and press Configure.
On the next page, add your domain and email and press Register on both.
After that verify the domain, press Download and download the .txt file in the next step.
Go into your website’s FTP server, create a folder with a name .well-known (yes, with the dot in front) and paste it inside.
To test if it’s working, type: https://PUT_YOUR_DOMAIN_HERE.com/.well-known/apple-developer-domain-association.txt and check if a text comes out as a result.
After that, go back and press Verify. (It might take time until Apple ‘see’ the file on your server.)
If it’s all good, you’ll see the following page:
Note:
Apple Official Doc is here.
You can download a sample app here (NXSSocialManager) but there is also an official one there.
“The best way to learn a new programming language is by writing programs in it.” — Dennis Ritchie