Firebase JWT的Flatter将GraphQL(GraphQL_flatter)请求发送给Heroku Hasura,该请求具有;格式错误的授权标头“;
我一直在寻找答案,但我还没有看到在一起使用flatter、Firebase和Hasura-GraphQL的上下文中讨论这个问题 在Flatter中工作,利用Firebase身份验证后端,我正在获取一个用户JWT并将其传递给Heroku Hasura GraphQL端点(带有一个查询) 大部分设置和代码都遵循并受到了中的教程第2部分和第3部分以及中的颤振图SQL文档的启发 Firebase正在成功地将新用户记录添加到我的GraphQL数据库中。Firebase正在返回一个JWT,并在构建GraphQL客户端期间将其添加到GraphQL AuthLink中。这就是JWT的样子(隐藏个人信息): 标题:算法和令牌类型Firebase JWT的Flatter将GraphQL(GraphQL_flatter)请求发送给Heroku Hasura,该请求具有;格式错误的授权标头“;,firebase,flutter,graphql,jwt,hasura,Firebase,Flutter,Graphql,Jwt,Hasura,我一直在寻找答案,但我还没有看到在一起使用flatter、Firebase和Hasura-GraphQL的上下文中讨论这个问题 在Flatter中工作,利用Firebase身份验证后端,我正在获取一个用户JWT并将其传递给Heroku Hasura GraphQL端点(带有一个查询) 大部分设置和代码都遵循并受到了中的教程第2部分和第3部分以及中的颤振图SQL文档的启发 Firebase正在成功地将新用户记录添加到我的GraphQL数据库中。Firebase正在返回一个JWT,并在构建Graph
{
"alg": "RS256",
"kid": "12809dd239d24bd379c0ad191f8b0edcdb9d3914",
"typ": "JWT"
}
FULL PAYLOAD:DATA
{
"iss": "https://securetoken.google.com/<firebase-app-id>",
"aud": "<firebase-app-id>",
"auth_time": 1598563214,
"user_id": "iMovnQvpwuO8HiGOV82cYTmZRM92",
"sub": "iMovnQvpwuO8HiGOV82cYTmZRM92",
"iat": 1598635486,
"exp": 1598639086,
"email": "<user-email>",
"email_verified": false,
"firebase": {
"identities": {
"email": [
"<user-email>"
]
},
"sign_in_provider": "password"
}
}
在我使用的各种教程和文档中,我看到定义hasura自定义声明的唯一需要是在Firebase cloud函数中注册用户:
exports.registerUser = functions.https.onCall(async (data, context) => {
const email = data.email;
const password = data.password;
const displayName = data.displayName;
if (email === null || password === null || displayName === null) {
throw new functions.https.HttpsError('unauthenticated', 'missing information');
}
try {
const userRecord = await admin.auth().createUser({
email: email,
password: password,
displayName: displayName
});
const customClaims = {
"https://hasura.io/jwt/claims": {
"x-hasura-default-role": "user",
"x-hasura-allowed-roles": ["user"],
"x-hasura-user-id": userRecord.uid
}
};
await admin.auth().setCustomUserClaims(userRecord.uid, customClaims);
return userRecord.toJSON();
} catch (e) {
throw new functions.https.HttpsError('unauthenticated', JSON.stringify(error, undefined, 2));
}
}))
我对Firebase和JWT来说太陌生了,无法理解为什么自定义声明不在令牌中。我以为Firebase会给我一个嵌入了自定义声明的JWT,把它传递给Hasura后端就足够了
我的Heroku Hasura应用程序日志也显示此错误:
“格式错误的授权标头”,“代码”:“无效标头”
Firebase是否需要进一步配置,以便归还正确的索赔?JWT中缺少的信息是否与记录为“格式错误的授权头”的服务器端错误相同,或者我是否需要设置其他头(请参阅下面的颤振代码)
以下是颤振中的GraphQL配置代码:
import 'dart:async';
import 'package:dailyvibe/services/jwt_service.dart';
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
class AuthLink extends Link {
AuthLink()
: super(
request: (Operation operation, [NextLink forward]) {
StreamController<FetchResult> controller;
Future<void> onListen() async {
try {
final String token = JWTSingleton.token;
operation.setContext(<String, Map<String, String>>{
'headers': <String, String>{
'Authorization': '''bearer $token'''
}
});
} catch (error) {
controller.addError(error);
}
await controller.addStream(forward(operation));
await controller.close();
}
controller = StreamController<FetchResult>(onListen: onListen);
return controller.stream;
},
);
}
class ConfigGraphQLClient extends StatefulWidget {
const ConfigGraphQLClient({
Key key,
@required this.child,
}) : super(key: key);
final Widget child;
@override
_ConfigGraphQLClientState createState() => _ConfigGraphQLClientState();
}
class _ConfigGraphQLClientState extends State<ConfigGraphQLClient> {
@override
Widget build(BuildContext context) {
final cache = InMemoryCache();
final authLink = AuthLink()
.concat(HttpLink(uri: 'https://<myapp>.herokuapp.com/v1/graphql'));
final ValueNotifier<GraphQLClient> client = ValueNotifier(
GraphQLClient(
cache: cache,
link: authLink,
),
);
return GraphQLProvider(
client: client,
child: CacheProvider(
child: widget.child,
),
);
}
}
导入'dart:async';
导入“包:dailyvibe/services/jwt_service.dart”;
进口“包装:颤振/材料.省道”;
导入“包:graphql_颤振/graphql_颤振.dart”;
类AuthLink扩展了链接{
AuthLink()
:超级(
请求:(操作操作,[NextLink forward]){
流量控制器;
Future onListen()异步{
试一试{
最终字符串标记=JWTSingleton.token;
操作.setContext({
“标题”:{
“授权”:“持票人$token”
}
});
}捕获(错误){
控制器。加法器(错误);
}
等待控制器addStream(转发(操作));
等待控制器。关闭();
}
控制器=流控制器(onListen:onListen);
返回控制器.stream;
},
);
}
类ConfigGraphQLClient扩展StatefulWidget{
const ConfigGraphQLClient({
关键点,
@需要这个孩子,
}):super(key:key);
最后一个孩子;
@凌驾
_ConfigGraphQLClientState createState()=>\u ConfigGraphQLClientState();
}
类_ConfigGraphQLClientState扩展状态{
@凌驾
小部件构建(构建上下文){
最终缓存=InMemoryCache();
final authLink=authLink()
.concat(HttpLink(uri:'https://.herokuapp.com/v1/graphql'));
最终ValueNotifier客户端=ValueNotifier(
GraphQLClient(
缓存:缓存,
链接:authLink,
),
);
返回GraphQLProvider(
客户:客户,,
子:缓存提供程序(
child:widget.child,
),
);
}
}
回答我自己的问题:自定义声明不在我的JWT中,因为我没有从Flatter调用我的registerUser云函数。现在我是这样的:
final HttpsCallable callable = CloudFunctions.instance
.getHttpsCallable(functionName: 'registerUser')
..timeout = const Duration(seconds: 30);
await callable.call(<String, dynamic>{
'email': email,
'password': password,
});
final httpscalable callable=CloudFunctions.instance
.GetHttpScalable(函数名:“registerUser”)
..超时=常数持续时间(秒:30);
等待呼叫({
“电子邮件”:电子邮件,
“密码”:密码,
});
(此代码段是由于)
相反,我使用Firebase的
createUserWithEmailAndPassword(email:email,password:password)
方法,它不会创建自定义声明或触发云函数。回答我自己的问题:自定义声明不在我的JWT中,因为我没有从Flatter调用我的registerUser云函数。现在我是这样的:
final HttpsCallable callable = CloudFunctions.instance
.getHttpsCallable(functionName: 'registerUser')
..timeout = const Duration(seconds: 30);
await callable.call(<String, dynamic>{
'email': email,
'password': password,
});
final httpscalable callable=CloudFunctions.instance
.GetHttpScalable(函数名:“registerUser”)
..超时=常数持续时间(秒:30);
等待呼叫({
“电子邮件”:电子邮件,
“密码”:密码,
});
(此代码段是由于)
相反,我使用的是Firebase的createUserWithEmailAndPassword(email:email,password:password)
方法,它不会创建自定义声明或触发云功能