簡體   English   中英

Firebase 用戶的 context.auth 仍然存在 allAuthenticatedUsers 使用 UNAUTHENTICATED 保護 Google 功能錯誤

[英]Firebase user's context.auth is present still allAuthenticatedUsers secured Google function error with UNAUTHENTICATED

我寫了一個簡單的函數:

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 從函數中刪除到“雲函數allUsers者”角色時,應用程序開始使用 UNAUTHENTICATED 代碼獲取PlatformException

以下是更改前設置的外觀:

變更前

添加allAuthenticatedUsers

添加 allAuthenticatedUsers

刪除allUsers

最終角色

然后當 Flutter 調用該函數時(當用戶登錄時),Flutter 會報錯

PlatformException(functionsError, Cloud function failed with exception., {message: UNAUTHENTICATED, details: null, code: UNAUTHENTICATED })

僅當用戶未登錄時才應顯示錯誤,但在任何一種情況下都會顯示錯誤。

allAuthenticatedUsers 的雲配置與 Firebase 以及它對可調用類型函數的身份驗證沒有任何關系。 Firebase 可調用函數與您更改的配置分開處理自己的身份驗證。 如果您希望 callables 正常工作,您應該將其改回。

您刪除的 allUsers 權限負責讓公眾(包括您的應用)可以訪問您的功能。 當您刪除它時,您實際上刪除了 Internet 上任何人能夠調用該函數的能力(這是可調用函數按設計運行所必需的)。

當您添加 allAuthenticatedUsers 時,您所做的只是要求調用者使用 Google 服務帳戶進行身份驗證。 同樣,這與 Firebase 或 Firebase Auth 無關。 這是一個 Google Cloud IAM 概念。 它不適用於可調用函數,因此您不應使用它。 我不清楚你為什么認為這是一個很好的配置。

如果您希望 Firebase 可調用函數從應用程序中正常調用,您應該將權限保留為默認的 allUsers,並讓 Firebase SDK 處理最終用戶的身份驗證。

閱讀有關GCP 訪問控制列表的更多信息,以了解您要更改的雲配置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM