![](/img/trans.png)
[英]Firebase function context.auth and context.authType undefined
[英]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
:
刪除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.