- 
          
- 
                Notifications
    You must be signed in to change notification settings 
- Fork 640
Open
Labels
β‘ websocketWeb Socket RelatedWeb Socket RelatedPriority: HighHigh priority to include it inside next releaseHigh priority to include it inside next release
Milestone
Description
I cannot seem to be able to use GraphQL subscriptions with my AWS server, by using Cognito authentication.
Queries and mutations work fine as far as I can tell, but I couldn't find how to connect to the amplify websocket.
Here is the code I tried, based on this comment: #682 (comment) (which I had to edit because Cognito tokens are not static)
import 'dart:async';
import 'dart:convert';
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_flutter/amplify_flutter.dart';
import 'package:flutter/material.dart';
import 'package:gql/language.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
String toBase64(Map data) => base64.encode(utf8.encode(jsonEncode(data)));
const apiId = "XXX";
const zone = "eu-west-1";
class AppSyncRequest extends RequestSerializer {
  final Map<String, dynamic> authHeader;
  const AppSyncRequest({
    required this.authHeader,
  });
  @override
  Map<String, dynamic> serializeRequest(Request request) => {
        "data": jsonEncode({
          "query": printNode(request.operation.document),
          "variables": request.variables,
        }),
        "extensions": {
          "authorization": authHeader,
        }
      };
}
ValueNotifier<GraphQLClient> buildClient() {
  Future<String?> _fetchSession() async {
    try {
      final session = await Amplify.Auth.fetchAuthSession(
              options: CognitoSessionOptions(getAWSCredentials: true))
          as CognitoAuthSession;
      if (!session.isSignedIn) {
        return null;
      }
      return session.userPoolTokens?.accessToken;
    } on AuthException catch (e) {
      debugPrintStack(label: e.toString());
    }
    return null;
  }
  Future<String?> _getIdToken() async {
    try {
      final session = await Amplify.Auth.fetchAuthSession(
              options: CognitoSessionOptions(getAWSCredentials: true))
          as CognitoAuthSession;
      if (!session.isSignedIn) {
        return null;
      }
      return session.userPoolTokens?.idToken;
    } on AuthException catch (e) {
      debugPrintStack(label: e.toString());
    }
    return null;
  }
  final HttpLink httpLink =
      HttpLink("https://$apiId.appsync-api.$zone.amazonaws.com/graphql");
  final WebSocketLink wsLink = WebSocketLink(
    'wss://$apiId.appsync-realtime-api.$zone.amazonaws.com/graphql',
    config: SocketClientConfig(
      initialPayload: () async {
        final token = await _fetchSession();
        return {
          "headers": {
            "Authorization": '$token',
            "host": "$apiId.appsync-api.$zone.amazonaws.com",
          },
        };
      },
    ),
  );
  final AuthLink authLink = AuthLink(
    getToken: _fetchSession,
  );
  // final Link link = authLink.concat(httpLink).concat(wsLink);
  final Link link = Link.split((request) => request.isSubscription,
      authLink.concat(wsLink), authLink.concat(httpLink));
  ValueNotifier<GraphQLClient> client = ValueNotifier(
    GraphQLClient(
      link: link,
      defaultPolicies:
          DefaultPolicies(query: Policies(fetch: FetchPolicy.cacheAndNetwork)),
      cache: GraphQLCache(
        partialDataPolicy: PartialDataCachePolicy.accept,
        store: HiveStore(),
      ),
    ),
  );
  return client;
}
class ClientProvider extends StatefulWidget {
  final Widget child;
  const ClientProvider({
    Key? key,
    required this.child,
  }) : super(key: key);
  @override
  State<ClientProvider> createState() => _ClientProviderState();
}
class _ClientProviderState extends State<ClientProvider> {
  @override
  Widget build(BuildContext context) {
    return GraphQLProvider(
      client: buildClient(),
      child: widget.child,
    );
  }
}- If I use the Link.split()method, my console is spammed withflutter: Disconnected from websocket.
- If I use the Link.concat()method, I get a HttpLinkServerException:GraphQLError(message: Subscriptions over MQTT is not supported., locations: null, path: null, extensions: null)
Naturally in both ways my Subscription widget doesn't work (infinite loading state).
Device / execution context
- Executed on macOS 12.4 (MacBook Pro M1 Pro)
- iOS 15.5
- Flutter 3.0.2
- graphql_flutter 5.1.0
- amplify_flutter 0.5.1
- amplify_api 0.5.1
- XCode 13.4.1
- VSCode 1.68.1
naedx
Metadata
Metadata
Assignees
Labels
β‘ websocketWeb Socket RelatedWeb Socket RelatedPriority: HighHigh priority to include it inside next releaseHigh priority to include it inside next release