повторная аутентификация пользователя приводит к тому, что облачная функция пожарного хранилища https.onCall () не получает аутентифицированную информацию о пользователе - PullRequest
0 голосов
/ 20 мая 2019

Вот настоящий головокружитель. У меня есть облачная функция, которая использует https.onCall (). Этот вызов функции вызывается из защищенной паролем области в моем приложении Android (я использую Firestore в качестве сервера). Чтобы получить доступ к этой области, я заставляю пользователя повторно вводить свой пароль, который затем вызывает FirebaseAuth.getInstance (). GetCurrentUser (). Reauthenticate ().

Я выполнил код, который вызывает облачную функцию https.onCall () без повторной аутентификации, и функция сохраняет учетные данные пользователя для аутентификации, поэтому я сузил его до некоторой степени при повторной аутентификации. Я что-то пропустил? Нужно ли что-то делать, чтобы сообщить облачной функции об обновлении аутентификации?

Сообщение об ошибке, которое я получал в журналах функций: Msgstr "Ошибка типа: невозможно прочитать свойство 'uid' неопознанного объекта". В частности, это происходило, когда я пытался получить uid аутентифицированного пользователя с помощью следующего:

const adminUID = context.auth.uid;

Предполагалось, что из-за того, что я не получил вышеуказанную ошибку, это потому, что не было аутентифицированных данных, поступающих через контекст.

Чтобы лучше понять, что происходит, вот мой поток / процесс:

Пользователь выбирает «Аккаунт» из меню настроек. Это запускает dialogFragment, который запрашивает пароль пользователя:

Код кнопки в диалоговом фрагменте:

 loginButton.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View view) {
            //execute the loginReAuth method
            authenticateSession.loginAdminReAuth(adminEmailAddress, passwordField);
        }
    });

После выбора кнопки loginButton и ввода пароля пользователем мы передаем данные в метод повторной аутентификации:

Повторно подтвердить подлинность кода:

public void loginAdminReAuth(final String email, TextView passwordText) {
    user = FirebaseAuth.getInstance().getCurrentUser();
    String password = passwordText.getText().toString();

    AuthCredential credential = EmailAuthProvider.getCredential(email, password);
    user.reauthenticate(credential)
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Intent intent = new Intent(context, AccountSettingsActivity.class);
                        context.startActivity(intent);
                    } else {
                        // If sign in fails, display a message to the user.
                        Log.w(TAG, "re-authenticate:failure", task.getException());
                        Toast.makeText(MyApplication.getContext(), task.getException().getMessage(),
                                Toast.LENGTH_SHORT).show();
                    }
                }
            });
}

Когда повторная аутентификация успешна, мы запускаем намерение и переносим их в AccountSettingsActivity. Внутри этого действия у меня есть метод: deleteAccount (), который запускается кнопкой, щелкает в alertDialog, подтверждающем действие.

Вот кнопка Click, которая вызывает метод:

@Override
public void onDialogOKPressed(DialogFragment dialog) {
    dialog.dismiss();
    if (buttonSelected.equals("accountUpdateButton")) {
       //update code here.
    }
    else if (buttonSelected.equals("accountDeleteButton")) {
        deleteAccount(admin);
    }
}

Вот метод deleteAccount (), который делает запрос облачной функции:

метод, который вызывает облачную функцию:

private Task<String> deleteAccount(Admin selectedAdmin) {
    Gson gson = new Gson();
    String selectedAdminJson;
    selectedAdminJson = gson.toJson(selectedAdmin);

    Map<String, Object> data = new HashMap<>();
    data.put("selectedAdminJson", selectedAdminJson);

    return mFunctions
            .getHttpsCallable("deleteAccount")
            .call(data)
            .continueWith(new Continuation<HttpsCallableResult, String>() {
                @Override
                public String then(@NonNull Task<HttpsCallableResult> task) throws Exception {
                    // This continuation runs on either success or failure, but if the task
                    // has failed then getResult() will throw an Exception which will be
                    // propagated down.
                    Log.d(TAG, "results from deleteAccount: " + task.getResult().getData().toString());
                    String result = (String) task.getResult().getData();
                    return result;
                }
            });
}

Наконец, вот код облачного пожарного хранилища, который выполняет запрос. Облачная функция https.onCall ():

// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
import * as functions from 'firebase-functions';
// The Firebase Admin SDK to access the Firebase Realtime Database.
import * as admin from 'firebase-admin'

export = module.exports = functions.https
.onCall(async (data, context) => {

    //selectedAdminJson received from app client and converted to admin object class
    const selectedAdminJson = data.selectedAdminJson;
    const adminUID = context.auth.uid;

    //Error checking
    // Checking attribute.
    if (!(typeof selectedAdminJson === 'string') || selectedAdminJson.length === 0) {
        // Throwing an HttpsError so that the client gets the error details.
        throw new functions.https.HttpsError('invalid-argument', 'The function must be called with ' +
            'one arguments "JSON object" containing selectedAdmin to add.');
    }
    // Checking that the user is authenticated OR if the calling adminID doesn't match the data received
    if (!context.auth) {
        // Throwing an HttpsError so that the client gets the error details.
        throw new functions.https.HttpsError('failed-precondition', 'The function must be called ' +
            'while authenticated.');
    }
    try {

        //METHODS EXECUTED HERE

    } catch (error) {
        console.error("Error removing adminUserGroup data: ", error);
    }

    // Returning result to the client.
    return {
        selectedAdminJson: "selectedAdminJson received and processing."
    };
});

Еще один кусок. Это часть моего index.ts:

import * as admin from 'firebase-admin'
admin.initializeApp();

if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === 'deleteAccount') {
    exports.deleteAccount = require('./deleteAccount');
}

1 Ответ

0 голосов
/ 20 мая 2019

Хорошо, я думаю, что решил проблему.Похоже, проблема заключалась в том, что я вышел из системы до того, как httpsCallable () смог полностью отправить информацию аутентификации.

Я делал следующее:

    deleteAccount(firebaseLocalCache.thisAdminFromCache());
    session.logoutUser();

Вместо этого я 'Вероятно, придется выполнить какое-то продолжение после метода deleteAccount (), который возвращает объект Task.Таким образом, мы выходим из системы ТОЛЬКО после получения ответа от сервера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...