Introduce
In the previous article , I and you learn how to log in using Apple ID in the iOS app. And recently, Google's Firebase has a beta support for Sign in With Apple in Firrebase Authentication, and in this article we will implement how to configure and implement Authenticate Using Apple on iOS using Firebase.
Authenticate Using Apple on iOS With Firebase
Before you begin
To log in using Apple, we first need to configure Sign In with Apple on Apple's developer site, then enable sign-in with Apple in your Firebase project.
Sign in with Apple and authenticate with Firebase
Have you reviewed the article and created the same project.
To authenticate with an Apple account, first use the AuthenticationServices framework to log in the user to the Apple account, then use the ID token from Apple's response to create a Firebase AuthCredential object:
Generate randomNonceString :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
extension ViewController { // Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce private func randomNonceString(length: Int = 32) -> String { precondition(length > 0) let charset: Array<Character> = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._") var result = "" var remainingLength = length while remainingLength > 0 { let randoms: [UInt8] = (0 ..< 16).map { _ in var random: UInt8 = 0 let errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random) if errorCode != errSecSuccess { fatalError("Unable to generate nonce. SecRandomCopyBytes failed with OSStatus (errorCode)") } return random } randoms.forEach { random in if length == 0 { return } if random < charset.count { result.append(charset[Int(random)]) remainingLength -= 1 } } } return result } } |
Create Sign in With Apple Button:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
private func configSigninWithAppleButton() { let authorizationButton = ASAuthorizationAppleIDButton() authorizationButton.addTarget(self, action: #selector(handleLogInWithAppleIDButtonPress), for: .touchUpInside) authorizationButton.frame = CGRect(x: 16, y: 250, width: 380, height: 46) view.addSubview(authorizationButton) } @objc private func handleLogInWithAppleIDButtonPress() { startSignInWithAppleFlow() } func startSignInWithAppleFlow() { let nonce = randomNonceString() currentNonce = nonce let appleIDProvider = ASAuthorizationAppleIDProvider() let request = appleIDProvider.createRequest() request.requestedScopes = [.fullName, .email] request.nonce = sha256(nonce) let authorizationController = ASAuthorizationController(authorizationRequests: [request]) authorizationController.delegate = self authorizationController.presentationContextProvider = self authorizationController.performRequests() } private func sha256(_ input: String) -> String { let inputData = Data(input.utf8) let hashedData = SHA256.hash(data: inputData) let hashString = hashedData.compactMap { return String(format: "%02x", $0) }.joined() return hashString } |
Handle ASAuthorizationControllerDelegate:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
extension ViewController: ASAuthorizationControllerDelegate { func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential { guard let nonce = currentNonce else { fatalError("Invalid state: A login callback was received, but no login request was sent.") } guard let appleIDToken = appleIDCredential.identityToken else { print("Unable to fetch identity token") return } guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else { print("Unable to serialize token string from data: (appleIDToken.debugDescription)") return } // Initialize a Firebase credential. let credential = OAuthProvider.credential(withProviderID: "apple.com", idToken: idTokenString, rawNonce: nonce) // Sign in with Firebase. Auth.auth().signIn(with: credential) { (authResult, error) in if error != nil { // Error. If error.code == .MissingOrInvalidNonce, make sure // you're sending the SHA256-hashed nonce as a hex string with // your request to Apple. print(error?.localizedDescription) return } // User is signed in to Firebase with Apple. // ... print("Signed in") // Sign in with Apple And Authenticate with Firebase Successfully } } } func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) { // Handle error. print("Sign in with Apple errored: (error)") } } |
After Sign in with Apple And Authenticate with Firebase is successful, on Firebase Authentication you will register an email with the format [email protected] . And the system absolutely can not know the user's real email, ensuring maximum safety for users.
Conclude
Above we together learn and make a simple example to perform Sign in with Apple and Authenticate with Firebase, we wait for the final release and can apply to our project. Thank you for reading the article
Reference: Firebase