Firebase user context.auth присутствует по-прежнему allAuthenticatedUsers исправил ошибку функции Google с UNAUTHENTICATED - PullRequest
0 голосов
/ 19 февраля 2020

Я написал простую облачную функцию:

import * as functions from 'firebase-functions';

export const repeat = functions.https.onCall( function (data, context) {
    // Authentication user information is automatically added to the request.
    if (context.auth) {
        console.log(' context.auth is defined ');
        console.log(' uid is ' + context.auth.uid);
    } else {
        console.log(' context.auth undefine. ');
    }
        if (context.auth) {
            return {
                repeat_message: context.auth.uid + ' ' + data.message,
                repeat_count: data.count + 1,
            };
        } else {
            return {
                repeat_message: ' noUID ' + data.message,
                repeat_count: data.count + 1,
            };
        }    }
);

И соответствующее приложение клиента Flutter:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:cloud_functions/cloud_functions.dart';

final FirebaseAuth _fAuth = FirebaseAuth.instance;

final GoogleSignIn _googleSignIn = GoogleSignIn(scopes: ['email'], signInOption: SignInOption.standard);

FirebaseUser _firebaseUser;
GoogleSignInAccount _googleSignInAccount;

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        textTheme: TextTheme(
          caption: TextStyle(
              fontSize: 20.0
          ),
          body1: TextStyle(
              fontSize: 20.0
          ),
        ),
      ),
      title: 'calling function',
      debugShowCheckedModeBanner: false,
      home: LaunchScreen(),
    );
  }
}

class LaunchScreen extends StatefulWidget {
  @override
  _LaunchScreenState createState() {
   return _LaunchScreenState();
  }
} // LoggingOptions  to _LaunchScreenState

class _LaunchScreenState extends State<LaunchScreen> {
  String _response = 'no response';
  int _responseCount = 1;
  final HttpsCallable callable = CloudFunctions.instance.getHttpsCallable(functionName: 'repeat')
    ..timeout = const Duration(seconds: 90);

  Future<FirebaseUser> _handleSignIn() async {
    try {
      GoogleSignInAccount googleSignInAccount = await _googleSignIn.signIn();
      _googleSignInAccount = googleSignInAccount;

      GoogleSignInAuthentication authentication = await googleSignInAccount.authentication;

      final AuthCredential credential = GoogleAuthProvider.getCredential(
        accessToken: authentication.accessToken, idToken: authentication.idToken,
      );
      AuthResult authResult;
      authResult = await _fAuth.signInWithCredential( credential);

      _firebaseUser = authResult.user;
      setState(() {});
      return _firebaseUser;
    } catch (e) {
      print(e.toString());
    }
    return null;
  }

  Future<void> _handleSignOut() async {
    FirebaseAuth.instance.signOut();
    _googleSignIn.signOut();

    setState(() {
      _firebaseUser =null;
      _googleSignInAccount= null;
    });
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
        appBar: AppBar( title: const Text('Sample Code'),),
        body: Center(
          child: Column(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              MaterialButton(
                  child: const Text( 'Sign in with Google', style: TextStyle(fontSize: 16.0),),
                  onPressed: () {
                    _handleSignIn().then((user) {
                      // logggedIn
                      debugPrint('user ' + user.toString());
                    }
                        );
                  },
                  ),

                 MaterialButton(
                  child: const Text( 'Sign out with Google', style: TextStyle(fontSize: 16.0),),
                  onPressed: () {
                    _handleSignOut();
                  },
                ),

              Text( _firebaseUser != null ? _firebaseUser.uid : 'user logged off'),

              Text('FromServer $_responseCount: $_response'),
              MaterialButton(
                child: const Text('SEND REQUEST', style: TextStyle(fontSize: 18.0),),
                onPressed: () async {
                  try {
                    final HttpsCallableResult result = await callable.call(
                      <String, dynamic>{
                        'message': 'hello',
                        'count': _responseCount,
                      }
                      ,
                    );
                    print(result.data);
                    setState(() {
                      _response = result.data['repeat_message'];
                      _responseCount = result.data['repeat_count'];
                    });
                  } on CloudFunctionsException catch (e) {
                    print('caught Firebase functions exception');
                    print(e.code);
                    print(e.message);
                    print(e.details);
                  } catch (e) {
                    print('caught generic exception');
                    print(e);
                  }
                },
              ),
            ],
          ),
        ));
  }    }

, и я могу видеть в обоих журналах сервера и на стороне клиента, что Auth передается корректно.

Но когда я добавляю allAuthenticatedUsers и удаляю allUsers к роли 'Cloud Functions Invoker' из функции , приложение начинает получать PlatformException с кодом UNAUTHENTICED.

Вот как выглядит настройка до изменения:

Before change

И после добавления allAuthenticatedUsers:

Adding allAuthenticatedUsers

После удаления allUsers:

Final roles

Затем при флаттере вызывает функцию (когда пользователь вошел в систему), Flutter ошибки с

PlatformException (functionsError, Cloud функция не выполнена с исключением., {message: UNAUTHENTICATED, подробности: ноль, код: UNAUTHENTICATED })

Ошибка должна отображаться только в том случае, если пользователь не вошел в систему, но она отображается в любом случае.

1 Ответ

2 голосов
/ 19 февраля 2020

Конфигурация облака для allAuthenticatedUsers никоим образом не связана с Firebase и тем, что она делает для аутентификации для функций вызываемого типа. Вызываемые функции Firebase обрабатывают свою собственную аутентификацию отдельно от конфигурации, которую вы изменили. Вы должны изменить его обратно, если хотите, чтобы вызываемые элементы работали должным образом.

Удаленное вами разрешение allUsers было ответственно за обеспечение доступности вашей функции для публикации c, включая ваше приложение. Когда вы удалили это, вы фактически исключили возможность для любого пользователя на inte rnet иметь возможность вызывать функцию (которая очень необходима для того, чтобы вызываемые функции работали как задумано).

Когда вы добавили allAuthenticatedUsers То, что вы сделали, это потребовали только абонентов, которые аутентифицируют себя с помощью учетной записи службы Google. Опять же, это не относится к Firebase или Firebase Auth. Это концепция Google Cloud IAM. Это не применимо для вызываемых функций, поэтому вы не должны его использовать. Мне непонятно, почему вы подумали, что это хорошая конфигурация.

Если вы хотите, чтобы вызываемые функции Firebase обычно вызывались из приложений, вам следует оставить разрешение по умолчанию allUsers и позволить Firebase SDK обработать аутентификацию конечного пользователя.

Подробнее о Списки управления доступом к Google Cloud , чтобы понять конфигурации облаков, которые вы изменяли.

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