Implementing Sign in with Apple
Sign in with Apple is a user-friendly authentication method that allows users to sign in to apps and websites using their Apple ID.
In this blog post, we'll explore how to integrate Sign in with Apple into your Swift-based iOS app for UIKit and SwiftUI based apps.
Overview
Sign in with Apple is a powerful authentication solution that simplifies user access to apps and websites.
Here's what you need to know:
-
Easy Sign-In: Instead of cumbersome forms and password management, users can sign in using their Apple ID. No more remembering passwords or verifying email addresses!
-
Privacy First: Apple prioritizes user privacy. Data collection is limited to the user's name and email address. Plus, Apple's private email relay ensures that users receive emails while keeping their address confidential.
-
Two-Factor Authentication: Every account using Sign in with Apple is automatically protected with two-factor authentication. Users on Apple devices can reauthenticate anytime with Face ID or Touch ID.
-
Cross-Platform Compatibility: Sign in with Apple works seamlessly across iOS, iPadOS, macOS, tvOS, and watchOS. It's also compatible with any browser, making it suitable for web and app development.
-
Antifraud Measures: Detect fake accounts with Apple's on-device machine learning. Get a privacy-friendly signal to identify genuine users.
Prerequisites
Before diving into implementation, ensure you have the following:
-
Apple Developer Account: You'll need an active Apple Developer account to configure Sign in with Apple.
-
Xcode: Make sure you have Xcode installed on your development machine.
Step-by-Step Implementation
1. Configure Your Project
- Open your project in Xcode.
- Navigate to the Signing & Capabilities pane.
- Set a unique bundle identifier for your app.
- Add your Apple ID account and assign the target to a team (enabling Sign in with Apple capability).
2. Add the Sign in with Apple Button
In your view controller or SwiftUI view, add the Sign in with Apple button. Here's how:
UIKit (View Controller)
import AuthenticationServices
class LoginViewController: UIViewController {
func setupProviderLoginView() {
let authorizationButton = ASAuthorizationAppleIDButton(
type: .signIn,
style: .whiteOutline
)
authorizationButton.addTarget(
self,
action: #selector(handleAuthorizationAppleIDButtonPress),
for: .touchUpInside
)
self.addSubview(authorizationButton)
}
@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()
}
}
// MARK: - Sign in with Apple
extension LoginViewController: ASAuthorizationControllerDelegate,
ASAuthorizationControllerPresentationContextProviding {
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return self.view.window!
}
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
let JWTToken = appleIDCredential.identityToken
let authCode = appleIDCredential.authorizationCode
dump(appleIDCredential)
// Close login window.
case let passwordCredential as ASPasswordCredential:
// Sign in using an existing iCloud Keychain credential.
let username = passwordCredential.user
let password = passwordCredential.password
print(passwordCredential)
// Close login window
default:
break
}
}
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
// Handle error.
print("Something went wrong", error)
}
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()
}
}
SwiftUI
import SwiftUI
import AuthenticationServices
struct ContentView: View {
var body: some View {
SignInWithAppleButton(.signIn) { request in
request.requestedScopes = [.fullName, .email]
} onCompletion: { result in
switch result {
case .success(let authorization):
if let userCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
dump(userCredential)
}
case .failure(let error):
print("Could not authenticate: \(error.localizedDescription)")
}
}
.signInWithAppleButtonStyle(.whiteOutline)
.frame(width: 280, height: 45)
}
}
SignInWithAppleButton(.label)
.continue
: Continue label
signIn
: Sign in with Apple label on the button.
signUp
: Sign up with Apple label on the button.
.signInWithAppleButtonStyle(.style)
black
: black button.
white
: white button.
whiteOutline
: white-outlined button.
Error codes
ASAuthorizationError.unknown
: Unknown error.
ASAuthorizationError.canceled
: User canceled the request.
ASAuthorizationError.failed
: Authorization failed.
ASAuthorizationError.invalidResponse
: Invalid response.
ASAuthorizationError.notHandled
: Request not handled.
ASAuthorizationError.unknown
: Unknown error.
3. User is signed in
Cache the name and email address of the user, this will be given once to the application.
Caveats
The user's name and email are only given once, this is expected behaviour.
It is recommened that you securely cache the initial ASAuthorizationAppleIDCredential containing the user info until you can validate that an account has succesfully been created on your server.
Source: https://forums.developer.apple.com/thread/121496#379297
Server-side validation may be needed, depending on your needs.
Conclusion
Sign in with Apple provides a seamless and secure authentication experience for your users.
It's easy to implement for usage in your app.
Resources
Read more
- @Environment variables • 4 minutes reading time.
- Snippet: @EnvironmentVariable • 1 minutes reading time.
- Pull-to-Refresh in SwiftUI • 2 minutes reading time.
Share
Share Mastodon Twitter LinkedIn Facebook