Я использую Firebase 3.0 и Swift v2.2. Я столкнулся с проблемой при использовании Firebase sendPasswordResetWithEmail, чтобы пользователи могли сбросить свои пароли в моем приложении iOS. Проблема в том, что адрес сброса пароля отправляется всем пользователям, даже тем пользователям, которые изначально не вошли в систему с Firebase, а вместо этого использовали кнопку входа в систему Google или кнопку входа в систему Facebook, также доступную в моем приложении. К сожалению, даже если пользователь получает электронное письмо и выполняет инструкции по сбросу пароля, ссылка, указанная в электронном письме с сбросом пароля, сбрасывает пароль только для тех учетных записей, которые вошли в систему Firebase; он не сбрасывает свой пароль Google или Facebook. Таким образом, они по-прежнему не смогут войти в систему.Разрешение при чтении провайдера (т. Е. Google, Facebook, Firebase), первоначально используемого для аутентификации пользователя Firebase 3.0
Мое решение было реализовать функцию getAuthProvider() (показано в коде, представленной ниже), чтобы получить первый поставщик, который я храню в мой пользователь узел в базе данных реального времени (как показано ниже), и в зависимости от поставщика я затем отправляю запрос на сброс пароля или покажу пользователю сообщение об ошибке, в котором говорится, что они должны сбросить пароль с помощью соответствующего провайдера.
Однако queryEqualToValue вызов возвращается к ошибке Permission Denied. Я обновил правила в своей базе данных реального времени Firebase (как показано ниже). Обратите внимание, так как пользовательские сброс своих паролей не являются аутентифицированными пользователями в то время, когда они запрашивают сброс пароля, я хотел бы предоставить им как можно меньше доступа. Я не хочу разрешать им получать доступ к имени и фамилии пользователя, я бы предпочел только предоставить им доступ к чтению провайдера. Что мне не хватает? Спасибо за любой вклад!
Firebase иерархия:
- пользователя
- UID
- электронный
- Firstname
- Lastname
- поставщик [значение s: «Firebase» или «Google.com» или «Facebook».ком "]
- UID
Firebase правила:
{
"rules": {
".read": "auth != null",
".write": "auth != null",
"user": {
"uid": {
"$provider": {
".read": true,
".write": "auth != null"
}
}
}
}
}
ViewController код:
import UIKit
import Firebase
class ResetPasswordTableViewController: UITableViewController, UITextFieldDelegate {
@IBOutlet weak var emailTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
//Hide navigation bar
self.navigationController?.navigationBarHidden = true
//Text fields delegates
self.emailTextField.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//--------------------------------------------------------
// MARK: Hide status bar
//--------------------------------------------------------
override func prefersStatusBarHidden() -> Bool {
return true
}
@IBAction func resetPasswordButtonTapped(sender: AnyObject?) {
//Set user fields
let email = emailTextField.text
// Check for empty fields
if (email!.isEmpty)
{
// Display error message
displayAlertMessage(REQUIRED_FIELDS_ERROR_TITTLE, message: REQUIRED_FIELDS_ERROR_MESSAGE)
return;
}
// Validate email address
if !(UserAccountValidator.validateEmailTextField(email!)) { //if invalid email format
// Display error message
self.displayAlertMessage(REENTER_EMAIL_ERROR_TITLE, message: REENTER_EMAIL_ERROR_TITLE)
return
}
// Get the current user's provider, only those users who were authenticated with Firebase as the provider should be sent a reset password email
let authProvider = getAuthProvider(email!)
if (!authProvider.isEmpty && authProvider == "Firebase") {
FIRAuth.auth()?.sendPasswordResetWithEmail(email!) { error in
// Back to main thread
NSOperationQueue.mainQueue().addOperationWithBlock {
if error != nil {
if let errorCode = FIRAuthErrorCode(rawValue: error!.code) {
switch (errorCode) {
case .ErrorCodeUserNotFound:
self.displayAlertMessage(EMAIL_NOTFOUND_3RDPARTY_ERROR_TITLE, message: EMAIL_NOTFOUND_3RDPARTY_ERROR_MESSAGE);
return
default:
self.displayAlertMessage(ACCOUNT_CREATION_DB_ERROR_TITLE, message: ACCOUNT_CREATION_DB_ERROR_MESSAGE);
return
}
}
} else {
// Present reset password success view
self.performSegueWithIdentifier("resetPasswordSuccessView", sender: self)
}
}
}
} else {
// Display error message
displayAlertMessage("Authentication Provider Mismatch", message: "It looks like you originally signed in with this email using Google or Facebook. Please reset your password with the appropriate provider and then come back and sign in with your new password.")
}
}
//--------------------------------------------------------
// MARK: Local Methods
//--------------------------------------------------------
func getAuthProvider(email: String) -> String {
//Retrieve Authentication Provider for a given UID
var authProvider: String = ""
FIRDatabase.database().reference().child("user").queryEqualToValue(email).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
// Get user value
authProvider = snapshot.value!["provider"] as! String
}) { (error) in
print(error.localizedDescription)
}
return authProvider
}
//--------------------------------------
// MARK: - Display Error Message Methods
//--------------------------------------
func displayAlertMessage(title:String,message:String)
{
let alertMessage = UIAlertController(title: title, message: message, preferredStyle:UIAlertControllerStyle.Alert);
let okAction = UIAlertAction(title:"OK", style: .Default, handler:nil);
alertMessage.addAction(okAction);
self.presentViewController(alertMessage, animated: true, completion: nil);
}
}