Last active
April 5, 2020 16:07
-
-
Save spaquet/353ef2e3aeef7437f321cec560cee11d to your computer and use it in GitHub Desktop.
AppleSignIn Singleton to use in SwiftUI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// AppleSignIn.swift | |
// | |
import Foundation | |
import FirebaseAuth | |
import AuthenticationServices | |
import CryptoKit | |
final class AppleSignIn: NSObject { | |
static let sharedInstance = AppleSignIn() | |
fileprivate var currentNonce: String? | |
func appleSignIn() { | |
let nonce = randomNonceString() | |
currentNonce = nonce | |
let appleIDProvider = ASAuthorizationAppleIDProvider() | |
let request = appleIDProvider.createRequest() | |
request.requestedScopes = [.email] | |
request.nonce = sha256(nonce) | |
let authorizationController = ASAuthorizationController(authorizationRequests: [request]) | |
authorizationController.presentationContextProvider = UIApplication.shared.windows.last?.rootViewController as? ASAuthorizationControllerPresentationContextProviding | |
authorizationController.delegate = self | |
authorizationController.performRequests() | |
} | |
// MARK: Some utilities | |
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 | |
} | |
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 remainingLength == 0 { | |
return | |
} | |
if random < charset.count { | |
result.append(charset[Int(random)]) | |
remainingLength -= 1 | |
} | |
} | |
} | |
return result | |
} | |
} | |
extension AppleSignIn: ASAuthorizationControllerDelegate { | |
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { | |
print("WE ARE HERE!") | |
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 let error = error { | |
// 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("User is now connectedr") | |
} | |
} | |
} | |
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) { | |
print("Error Signing in with Apple ID: \(error.localizedDescription)") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment