I've implemented a Sign In With Apple as the front end, and Firebase as the backend. The objective is that the user would sign in, and the terminal would give the user's name and email. For some reason, it isn't working. Please take a look and tell me what I am missing to make it do what my goal is.
import SwiftUI
import Firebase
import AuthenticationServices
import FirebaseAuth
import CryptoKit
struct LoginView: View {
@State private var isLoginMode = false
@State private var email = ""
@State private var password = ""
@State private var address = ""
@State private var resultOfAuth = ""
@EnvironmentObject var userAuth: UserAuth
@State var currentnonce: String?
// 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: [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
}
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
}
var body: some View {
NavigationView {
SignInWithAppleButton(
onRequest: { request in
let nonce = randomNonceString()
currentnonce = nonce
request.requestedScopes = [.fullName, .email]
request.nonce = sha256(nonce)
let resultOfAuth = request.requestedScopes
},
onCompletion: { result in
switch result {
case .success(let authResults):
switch authResults.credential {
case let appleIDCredential 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 {
fatalError("Invalid state: A login callback was received, but no login request was sent.")
}
guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else {
print("Unable to serialize token string from data: \(appleIDToken.debugDescription)")
return
}
let credential = OAuthProvider.credential(withProviderID: "apple.com",idToken: idTokenString,rawNonce: nonce)
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
}
print("signed in")
print(resultOfAuth)
self.userAuth.login()
NavigationLink {
HomeView()
} label: {
Text("Done")
}
}
print("\(String(describing: Auth.auth().currentUser?.uid))")
default:
break
}
default:
break
}
}
)
.frame(width: 200, height: 45, alignment: .center)
}
}
```
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hi, Is there any way that I can make an app that lets users with different apple-ids upload, read, and write data into the cloud. If there is, is there a tutorial that I could follow?
Thanks :)
For some reason, my code keeps on showing up as an Optional and it's not letting my geocoder work. Any help is appreciated :)
import MapKit
import CoreLocationUI
import Firebase
struct Place: Identifiable {
let id = UUID()
var name: String
var coordinate: CLLocationCoordinate2D
}
struct MapView: View {
var empireStateBuilding =
Place(name: "Empire State Building", coordinate: CLLocationCoordinate2D(latitude: 40.748433, longitude: -73.985656))
@StateObject private var viewModel = ContentViewModel()
@State var address = ""
@State var addresses:[String] = []
@State private var multipleAddress = ""
let geocoder = CLGeocoder()
@State private var result = "result of lat & long"
@State private var lat = 0.0
@State private var long = 0.0
@State private var country = "country name"
@State private var state = "state name"
@State private var zip = "zip code"
var body: some View {
NavigationView {
ZStack (alignment: .bottom) {
Map(coordinateRegion: $viewModel.region, showsUserLocation: true)
.ignoresSafeArea()
.tint(.pink)
LocationButton(.currentLocation) {
viewModel.requestAllowOnceLocationPermission()
}
.foregroundColor(.white)
.cornerRadius(8)
.labelStyle(.iconOnly)
.symbolVariant(.fill)
.tint(.pink)
.padding(.bottom)
.padding(.trailing, 300)
Button {
let multipleAddresses = addresses
geocoder.geocodeAddressString(multipleAddress, completionHandler: {(placemarks, error) -> Void in
if((error) != nil){
print("Error", error ?? "")
}
if let placemark = placemarks?.first {
let coordinates:CLLocationCoordinate2D = placemark.location!.coordinate
print("Lat: \(coordinates.latitude) -- Long: \(coordinates.longitude)")
//added code
result = "Lat: \(coordinates.latitude) -- Long: \(coordinates.longitude)"
lat = coordinates.latitude
long = coordinates.longitude
print(result)
print(addresses)
}
})
} label: {
Image(systemName: "arrow.clockwise")
}
.padding(.leading, 300)
.padding(.bottom)
.cornerRadius(8)
}
List(0..<addresses.count, id: \.self) {i in Text(addresses[i]) }
}
.onAppear(perform: {
downloadServerData()
})
}
func downloadServerData() {
let db = Firestore.firestore()
db.collection("UserInfo").addSnapshotListener {(snap, err) in
if err != nil{
print("There is an error")
return
}
for i in snap!.documentChanges {
let documentId = i.document.documentID
let address = i.document.get("address")
DispatchQueue.main.async {
addresses.append("\(address)")
print(address)
}
}
}
}
struct AnnotatedItem: Identifiable {
let id = UUID()
var name: String
var coordinate: CLLocationCoordinate2D
}
struct MapView_Previews: PreviewProvider {
static var previews: some View {
MapView()
}
}
//LocationButton
final class ContentViewModel: NSObject, ObservableObject, CLLocationManagerDelegate {
@Published var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 40, longitude: 120), span: MKCoordinateSpan(latitudeDelta: 100, longitudeDelta: 100))
let locationManager = CLLocationManager()
override init() {
super.init()
locationManager.delegate = self
}
func requestAllowOnceLocationPermission() {
locationManager.requestLocation()
}
func locationManager( _ _manager:CLLocationManager, didUpdateLocations locations: [CLLocation]){
guard let latestLocation = locations.first else {
// show an error
return
}
DispatchQueue.main.async{
self.region = MKCoordinateRegion(
center: latestLocation.coordinate,
span:MKCoordinateSpan(latitudeDelta:0.05, longitudeDelta:0.05))
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print(error.localizedDescription)
}
}
}
struct MapView_Previews: PreviewProvider {
static var previews: some View {
MapView()
}
}
For some reason, my Xcode previews keep on disappearing, saying that they timeout.
I have Xcode 13 and Mac OS Monterey Beta.
For some reasons when I have 2 view controllers, both respective swift files are not showing up. I have tried relinking both of them. What should I do?