I am trying to write code in Unity to read a document in Firestore. I have a login code in one class that uses Firebase's email and password authentication. In another class I utilize Firestore objects try to access the document on Firestore, but I get the error:
Failed to register task with System.AggregateException: One or more errors occurred. ---> Firebase.Firestore.FirestoreException: Missing or insufficient permissions.
Below is the rules for Firestore:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read: if request.auth != null;
}
}
}
This is a snippet code for the login class:
private IEnumerator CheckDependencies()
{
var checkAndFixDependenciesTask = FirebaseApp.CheckAndFixDependenciesAsync();
yield return new WaitUntil(predicate: () => checkAndFixDependenciesTask.IsCompleted);
var dependencyResult = checkAndFixDependenciesTask.Result;
if (dependencyResult == DependencyStatus.Available)
{
InitializeFirebase();
}
else
{
Debug.Log($"Error. Details: {dependencyResult}");
}
}
public void InitializeFirebase()
{
auth = FirebaseAuth.DefaultInstance;
auth.StateChanged += Auth_StateChanged;
Auth_StateChanged(this, null);
Debug.Log("Firebase Initialized");
}
private void Auth_StateChanged(object sender, System.EventArgs e)
{
if (auth.CurrentUser != user)
{
bool signedIn = user != auth.CurrentUser && auth.CurrentUser != null;
if (!signedIn && user != null)
{
Debug.Log("Signed Out");
}
user = auth.CurrentUser;
if (signedIn)
{
Debug.Log($"Signed In: {user.Email}");
}
}
}
public IEnumerator RegisterEmailAndPassword(string email, string password, string username)
{
//StartCoroutine(CheckDependencies());
var registerTask = auth.CreateUserWithEmailAndPasswordAsync(email, password);
yield return new WaitUntil(predicate: () => registerTask.IsCompleted);
Debug.Log("Register called.");
if (registerTask.Exception != null)
{
//If there are errors handle them
Debug.LogWarning(message: $"Failed to register task with {registerTask.Exception}");
FirebaseException firebaseException = registerTask.Exception.GetBaseException() as FirebaseException;
AuthError errorCode = (AuthError)firebaseException.ErrorCode;
Debug.Log($"Exception: {registerTask.Exception} | Error: {errorCode}");
switch (errorCode)
{
case AuthError.MissingEmail:
errorMessage = "Missing Email";
break;
case AuthError.MissingPassword:
errorMessage = "Missing Password";
break;
case AuthError.WeakPassword:
errorMessage = "Weak Password";
break;
case AuthError.EmailAlreadyInUse:
errorMessage = "Email Already In Use";
break;
}
}
else
{
user = registerTask.Result;
if (user != null)
{
UserProfile profile = new UserProfile { DisplayName = username };
var profileTask = user.UpdateUserProfileAsync(profile);
yield return new WaitUntil(predicate: () => profileTask.IsCompleted);
if (profileTask.Exception != null)
{
Debug.LogWarning(message: $"Failed to register task with {profileTask.Exception}");
FirebaseException firebaseException = profileTask.Exception.GetBaseException() as FirebaseException;
AuthError errorCode = (AuthError)firebaseException.ErrorCode;
}
else
{
StartCoroutine(SendVerificationEmail());
Debug.Log("Verification Sent");
}
}
}
}
public IEnumerator SignInEmailAndPassword(string email, string password)
{
//StartCoroutine(CheckDependencies());
var loginTask = auth.SignInWithEmailAndPasswordAsync(email, password);
yield return new WaitUntil(predicate: () => loginTask.IsCompleted);
if (loginTask.Exception != null)
{
//If there are errors handle them
Debug.LogWarning(message: $"Failed to register task with {loginTask.Exception}");
FirebaseException firebaseException = loginTask.Exception.GetBaseException() as FirebaseException;
AuthError error = (AuthError)firebaseException.ErrorCode;
switch (error)
{
case AuthError.MissingEmail:
errorText.text = "Email is missing";
break;
case AuthError.MissingPassword:
errorText.text = "Password is missing";
break;
case AuthError.WrongPassword:
errorText.text = "Incorrect Password";
break;
case AuthError.InvalidEmail:
errorText.text = "Email is invalid";
break;
case AuthError.UserNotFound:
errorText.text = "Account does not exist.";
break;
default:
errorText.text = "Unknown error";
break;
}
loginError.SetActive(true);
usernameField.text = "";
passwordField.text = "";
}
else
{
user = loginTask.Result;
if (!user.IsEmailVerified)
{
//Tell user to verify email and sign user out
//Debug.LogFormat("User: {0} Email: {1} Not verified!", user.DisplayName, user.Email);
StartCoroutine(SendVerificationEmail());
errorText.text = $"User: {user.DisplayName} Email: {user.Email} Not verified!";
auth.SignOut();
}
else
{
//Debug.LogFormat("User signed in: {0} ({1})", user.DisplayName, user.Email);
//display main page
}
}
}
public IEnumerator SendVerificationEmail()
{
var verificationTask = user.SendEmailVerificationAsync();
yield return new WaitUntil(predicate: () => verificationTask.IsCompleted);
if (verificationTask.Exception != null)
{
Debug.LogWarning(message: $"Failed to register task with {verificationTask.Exception}");
FirebaseException firebaseException = verificationTask.Exception.GetBaseException() as FirebaseException;
AuthError error = (AuthError)firebaseException.ErrorCode;
switch (error)
{
case AuthError.InvalidEmail:
errorMessage = "Email is invalid";
break;
default:
errorMessage = "Unknown error: " + error;
break;
}
}
else
{
Debug.Log("Verification Email Sent");
}
}
Below is the snippet to access Firestore document:
public FirebaseFirestore firestore;
public void Start(){
indicator = FindObjectOfType<OfflineIndicator>();
firestore = FirebaseFirestore.DefaultInstance;
StartCoroutine(FetchRefreshToken());
}
public IEnumerator FetchRefreshToken()
{
DocumentReference db = firestore.Collection("school").Document("info");
var task = db.GetSnapshotAsync();
yield return new WaitUntil(predicate: () => task.IsCompleted);
if (task.Exception != null)
{
Debug.Log($"Failed to register task with {task.Exception}");
FirebaseException firebaseException = task.Exception.GetBaseException() as FirebaseException;
FirestoreError error = (FirestoreError)firebaseException.ErrorCode;
Debug.Log("Firestore Error Code: " + error);
}
else
{
DocumentSnapshot documentSnapshot = task.Result;
Dictionary<string, object> docS = documentSnapshot.ToDictionary();
//Debug.Log("Token " + docS["name"].ToString());
name = docS["name"].ToString();
}
}
I create the necessary objects and call the required coroutines but I still get an error. It only works when I allow all access in Firestore rules.