'SwiftUI - Firebase Apple Auth not authenticating
im fairly new to swiftUI... pardon the ignorance :) I have most of the code entered in my project from the instructions on the Firebase website. For some reason apple authentication will not successfully authenticate. No idea why, I suspect the nonce part of the code located in 'ConentView' is potentially not being linked to the service. If anyone has any thoughts on why this is occurring I would be greatly appreciative for any help?
Xcode simulator - will not load past this screen
ContentView:
import SwiftUI
import FirebaseAuthUI
import CryptoKit
import AuthenticationServices
struct ContentView: View {
private func sha256(_ input: String) -> String {
let inputData = Data(input.utf8)
let hashedData = SHA256.hash(data: inputData)
let hashString = hashedData.compactMap {
String(format: "%02x", $0)
}.joined()
return hashString
}
@ObservedObject private var authStateManager =
FirebaseAuthStateManager()
@State var isShowSheet = false
@State var currentNonce:String?
private func randomNonceString(length: Int = 32) ->
String {
precondition(length > 0)
let charset: [Character] =
***key***
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
}
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 as Any)
return
}
// User is signed in to Firebase with Apple.
// ...
}
}
func authorizationController(controller:
ASAuthorizationController, didCompleteWithError error:
Error) {
// Handle error.
print("Sign in with Apple errored: \(error)")
}
}
var body: some View {
VStack {
if authStateManager.signInState == false {
// Sign-Out
Button(action: {
self.isShowSheet.toggle()
}) {
Text("Sign-In")
}
} else {
// Sign-In
Button(action: {
do {
try Auth.auth().signOut()
} catch {
print("Error")
}
}) {
Text("Sign-Out")
}
}
}
.sheet(isPresented: $isShowSheet) {
FirebaseUIView(isShowSheet: self.$isShowSheet)
}
}
}
FirebaseUIView:
import SwiftUI
import FirebaseAuthUI
import FirebaseGoogleAuthUI
import FirebaseOAuthUI
import CryptoKit
import AuthenticationServices
import FirebaseEmailAuthUI
struct FirebaseUIView: UIViewControllerRepresentable {
@Binding var isShowSheet: Bool
class Coordinator: NSObject,
FUIAuthDelegate {
// FirebaseUIView
let parent: FirebaseUIView
//
init(_ parent: FirebaseUIView) {
self.parent = parent
}
// MARK: - FUIAuthDelegate
func authUI(_ authUI: FUIAuth, didSignInWith user:
User?, error: Error?) {
// handle user and error as necessary
if let error = error {
//
print("Auth NG:\
(error.localizedDescription)")
}
if let _ = user {
//
}
// Sheet(ModalView)
parent.isShowSheet = false
}
}
func makeCoordinator() -> Coordinator {
// Coordinator
Coordinator(self)
}
func makeUIViewController(context: Context) ->
UINavigationController {
let authUI = FUIAuth.defaultAuthUI()!
// You need to adopt a FUIAuthDelegate protocol to
receive callback
authUI.delegate = context.coordinator
let providers: [FUIAuthProvider] = [
FUIGoogleAuth(authUI: authUI),
FUIOAuth.microsoftAuthProvider(),
// FUIFacebookAuth(authUI: authUI),
// FUIOAuth.twitterAuthProvider(),
FUIEmailAuth(),
// FUIPhoneAuth(authUI:authUI),
FUIOAuth.appleAuthProvider(),
]
authUI.providers = providers
// FirebaseUI
let authViewController = authUI.authViewController()
return authViewController
}
func updateUIViewController(_ uiViewController:
UINavigationController, context: Context) {
}
}
[ContentView[][2]2
Solution 1:[1]
Turns out there was nothing wrong with my code. The moment I switched from simulator to the actual iPhone device the code worked perfectly. This is a known BUG with the simulator in Xcode.
Solution 2:[2]
Check out SignInWithApple from FirebaseService: https://github.com/rebeloper/FirebaseService
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Erinballs |
Solution 2 | Rebeloper |