zino-hofmann / graphql-flutter

A GraphQL client for Flutter, bringing all the features from a modern GraphQL client to one easy to use package.
https://zino-hofmann.github.io/graphql-flutter
MIT License
3.25k stars 620 forks source link

Implementing SSL Pinning with Flutter GraphQL #1157

Closed serpentarius-hollow closed 2 years ago

serpentarius-hollow commented 2 years ago

Hi there,

I'm trying to implement SSL Pinning using your library with another library called http_certificate_pinning. The issue is gqlClient always returned connection secure even if the allowedSHAFingerprints is not valid.

Here's my stackoverflow question to help you see my code: link

Thank you.

budde377 commented 2 years ago

Please provide some more details on what you're expecting vs what you're seeing and a reproducible example.

serpentarius-hollow commented 2 years ago

I'm expecting gqlClient throwing error on query perform here:

final secureClient = GetIt.I<Service>().gqlClient;
final options = QueryOptions(
  document: gql(homePageQuery),
);
final result = await secureClient.query(options);

Because I set the wrong allowedSHAFingerprints on class Service constructor

The actual result is connection success and it fired a snackbar like in my code above.

budde377 commented 2 years ago

Alright, so this is really a problem with how the HttpLink (gql_http_link) works with the secure secureClient.

If you have a look at the HttpLink implementation, you'll notice that it's calling .send on the provided HTTP client https://github.com/gql-dart/gql/blob/master/links/gql_http_link/lib/src/link.dart#L169. Now, the secure client doesn't implement any checking for the send method: https://github.com/diefferson/http_certificate_pinning/blob/master/lib/src/http_client/secure_http_client.dart#L63.

It seems like you have two options:

Personally, I'd go for the second option.

Regardless, this is not a bug in this package, so I'll close the issue. I hope you find a solution and please feel free to share it here if you do!

serpentarius-hollow commented 2 years ago

Finally solved this problem.

I'm using dio and another library called gql_dio_link

Here's my implementation of Service class now:

import 'package:dio/dio.dart';
import 'package:gql_dio_link/gql_dio_link.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:http_certificate_pinning/http_certificate_pinning.dart';

class Service {
  final List<String> _allowedSHAFingerprints;

  late GraphQLClient _secureGqlClient;
  GraphQLClient get secureGqlClient => _secureGqlClient;

  late Dio _secureDioClient;
  Dio get secureDioClient => _secureDioClient;

  Service(this._allowedSHAFingerprints) {
    _secureDioClient = Dio(BaseOptions(baseUrl: 'https://dummy.com'))
      ..interceptors.add(CertificatePinningInterceptor(
          allowedSHAFingerprints: _allowedSHAFingerprints));

    final link = Link.from([
      DioLink(
        '/graphql',
        client: _secureDioClient,
      ),
    ]);

    _secureGqlClient = GraphQLClient(
      link: link,
      cache: GraphQLCache(),
    );
  }
}
budde377 commented 2 years ago

@serpentarius-hollow thanks for sharing your solution!

vincenzopalazzo commented 2 years ago

Thinking if we should create a Q&A document to include all these solutions, looks like that dio solve different problems for graphql_flutter.

What do you think?