I am working on sign up page of application in Swift. The part of authentication in Firebase works well, but the database doesn't save any information I request. Can anyone help?
My code:
Auth.auth().createUser(withEmail: userEmail,password: userPassword, completion: {(User, error) in
if error != nil {
print(error as Any)
return
}
guard let uid = User?.user.uid else {return}
let ref = Database.database().reference(fromURL:"Database-URL")
let userReference = ref.child("users").child(uid)
let values = ["Firstname": userFirstName,"email": userEmail]
userReference.updateChildValues(values, withCompletionBlock: { (error, reference) in
if error != nil {
print(error as Any)
return
}
})
})
The console prints an error
Optional(Error Domain=com.firebase Code=1 "Permission denied"
UserInfo={NSLocalizedDescription=Permission denied})
By default the database in a project in the new Firebase Console is only readable/writeable by authenticated users:
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
See the quickstart for the Firebase Database security rules.
Since you're not signing the user in from your code, the database denies you access to the data. To solve that you will either need to allow unauthenticated access to your database, or sign in the user before accessing the database.
Allow unauthenticated access to your database
The simplest workaround for the moment (until the tutorial gets updated) is to go into the Database panel in the console for you project, select the Rules tab and replace the contents with these rules:
{
"rules": {
".read": true,
".write": true
}
}
This makes your new database readable and writeable by everyone. Be certain to secure your database again before you go into production, otherwise somebody is likely to start abusing it.
I may not be sure but the completion for createUser doesnot give you User and error rather AuthResult and Error. So you have to get the user from result as below
Auth.auth().createUser(withEmail: email, password: password) { (authData, error) in
if let error = error {
debugPrint("FIREBASE ERROR : \(error.localizedDescription)")
} else {
if let authData = authData {
let user = authData.user //here get the user from result
self.saveToDB(user: user) . //save the user to database
}
}
}
This is the new code for firebase from may 2019. just change false to true like this:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true;
}
}
}
Related
I am trying to create a node in database in Firebase but nothing happens.
Auth.auth().createUser(withEmail: (emailTextField.text!), password: (passwordTextField.text!)) { (result, error) in
if let _eror = error {
print(_eror.localizedDescription )
} else {
var ref: DatabaseReference!
ref = Database.database().reference()
ref.child("users").child((result?.user.uid)!).setValue(["username": self.usernameTextField.text!])
}
}
Here is in the console
When I click 'Sign Up', I find that it's still having a new user created in Firebase.
The console output you shared shows the error:
setValue: or removeValue: at /users/E7... failed permission_denied
Check the rules for your Firebase project database and ensure that write access is granted
{
"rules": {
"users":{
"$user_id": {
".write": "auth.uid == user_id"
}
}
}
}
guard let uid = user?.uid else {return}
let usernameValue = ["username":username]
let value = [uid: usernameValue]
Database.database().reference().child("user").updateChildValues(value, withCompletionBlock: { (err, ref) in
if let err = err{
print("failed to save user in db:", err)
}else{
print("successfully Work")
}
})
This is the error I am facing:
failed to save user in db: Error Domain=com.firebase Code=1 "Permission denied" UserInfo={NSLocalizedDescription=Permission denied}
You do not have the permission to manage the /user path in the database.
Check your Firebase security rules.
Allow unauthenticated access to your database.
Go into the Database panel in the console for you project, select the Rules tab and replace the contents with these rules:
{
"rules": {
".read": true,
".write": true
}
}
This makes your new database readable and writeable by everyone.
One more trick to avoid this problem call one of the signIn...methods of Firebase Authentication to ensure the user is signed in before accessing the database.
I'm currently developing an IOS app and what i want to do is differentiate between admin users and normal users when logging into the app because at the moment a normal user can log in and get access to the admin options. I'm using Firebase as my database but there's no option to differentiate. Any help would be much appreciated.
Here's my code for login
#IBAction func loginTapped(_ sender: Any) {
if let email = emailTextField.text, let password = passwordTextField.text{
Auth.auth().signIn(withEmail: email, password: password) {(user, error) in
if let firebaseError = error{
print (firebaseError.localizedDescription)
self.showAlert("Invalid Email or Password")
return
}
self.presentLoggedInScreen()
}
}
}
I accept if anyone downvotes this post but please comment below why you doing so. Thanks
You need to use other things to implement some role based authentication, you can check examples here to give you some ideas: https://firebase.google.com/docs/auth/admin/custom-claims
You can add rules to your Firebase database:
Got to your database on your Firebase console then click on your Rule Tab on you right side and add one of the following examples adapted to your code.
For example, here everyone has access to your /foo/ path but no one can write to it:
service cloud.firestore{
"rules": {
"foo": {
".read": true,
".write": false
}
}
}
So, if you want a certain autoriztion to some path for determinated users you can do it as follows:
service cloud.firestore{
"rules": {
"users": {
"$uid": {
"foo": {
".read": true,
".write": false
}
}
}
}
}
Or you can do it with a parameter to restrict foo access to a specific uid:
"foo":{
".read": "auth.uid != null &&
query.orderByChild == 'owner' && query.equalTo == auth.uid"
}
I am working on an app that requires Firebase auth and database. When registering, the app must check to see if the code entered is genuine then proceed to create a user. This is my code:
ref = FIRDatabase.database().reference()
self.ref.child("PatientCodes").observeSingleEvent(of: .value, with: { (snaphshot) in
print("In")
let value = snaphshot.value as! NSArray
if value.contains(self.patientIDTextField.text!) {
print("Found ID")
FIRAuth.auth()?.createUser(withEmail: self.emailTextField.text!, password: self.passwordTextField.text!, completion: { (user, error) in
if user != nil {
self.performSegue(withIdentifier: "registered", sender: self)
}
})
}
The issue I am having is, none of the code is being executed past self.ref.child etc. The print("In") statement is never hit.
Any help is greatly appreciated. Thanks in advance.
Before starting anything with Firebase Database,
first check that the rules under database in your console is properly set i.e whether read is true or write is true.
Look at your database's rules, the default rule prevents anonymous read and write, so you must log in first to get access to the database.
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
I've incorporated a sign-up flow of five view controllers as opposed to one central VC for Firebase sign up.
Normally there would be the problem of data being lost before sign up, but I'm pushing all the entered values via segue programmatically to the final confirmation page and sending the data to Firebase for auth eventually.
My problem lies therein - I want to check if the username exists before signing up. This is imperative for the UX of my app and I can't just do this all one VC.
Here's the code I have for the UsernameViewController:
let rootRef = FIRDatabase.database().reference()
rootRef.queryOrdered(byChild: "users").queryEqual(toValue: self.chooseUsernameTextField.text!)
.observe(FIRDataEventType.value, with: { (snapshot: FIRDataSnapshot!) in
if snapshot.hasChildren() == false {
print("not found")
} else {
print("usr found")
}
});
Here's the code I have for the Firebase Database Security Rules
{
"rules": {
".read": false,
".write": false,
"users": {
".validate": "data.child('username').val() === true",
".read": true
}
}
}
and finally, a screenshot of my Data tree (My Data tree won't let me nest any new users or create a user node without a value for some reason):
Picture of Firebase Data Tree: App Name/Users
I have a nagging suspicion that my data rules and tree are configured properly to match the code, but I'm stuck in a XY problem of not knowing what to do for Firebase security to get my code of username checking complete.
Please help me! :(
If there's a user created within the Auth section of Firebase as well, then you can actually use the fetchProviders method, and if no providers are returned, you have no user in you Auth section.
FIRAuth.auth()?.fetchProviders(forEmail: email, completion: { (providers, error) in
if providers == nil {
// user doesn't exist
} else {
// user does exist
}
})
I have not tested the code but the theory would be to order by username that equals to the username you are looking for. If this snapshot exists you already have a user in the database with that name if it doesn't you do not.
Will run and test code when i have a chance to and update my post.
let rootRef = FIRDatabase.database().reference()
rootRef.child("users").queryOrdered(byChild:"username").queryEqual(toValue: self.chooseUsernameTextField.text!)
.observe(.value, with: { (snapshot) in
if snapshot.exists() == false {
print("not found")
} else {
print("usr found")
}
});
When using Firestore to save users, I did this
Auth.auth().addStateDidChangeListener({ (auth, user) in
if let id = user?.uid{
let userDoc = db.collection("users").document(id)
userDoc.getDocument { (document, error) in
if document == nil{// if user doesn't exist, create one
self.db.collection("users").document(id).setData(userProfile.toDictionary()){ error in
}
}
}
}
})