[英]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.