Approov is an API security solution used to verify that requests received by your backend services originate from trusted versions of your mobile apps.
This is an Approov integration quickstart for using Flutter with GraphQL, specifically a Dart client for GraphQL subscriptions via Absinthe sockets. Additionally, a step-by-step tutorial guide using a Todo App is also available.
Note that the minimum OS requirement for iOS is 12 and for Android the minimum SDK version is 23 (Android 6.0). You cannot use Approov in apps that need to support OS versions older than this.
This quickstart does not currently work because the packages in https://github.com/absinthe-graphql/absinthe-socket have not been updated to be compatible with Flutter 3.x versions. Please contact Approov support if you require an updated version.
Approov Enabled Flutter GraphQL is available via a Github package. This allows inclusion into the project by simply specifying a dependency in the pubspec.yaml files for the app. In the dependencies: section of pubspec.yaml file add the following package reference:
absinthe_socket:
  git:
    url: https://github.com/approov/approov-flutter-packages.git
    path: absinthe_socket
approov_service_flutter_httpclient:
  git: https://github.com/approov/approov-service-flutter-httpclient.gitNote that this creates a dependency on the latest version of the approov-service-flutter-httpclient, as do the dependencies in approov-flutter-packages. If you wish to create a dependency on a fixed tagged version you can use a syntax such as the following:
approov_service_flutter_httpclient:
  git:
    url: https://github.com/approov/approov-service-flutter-httpclient.git
    ref: 3.3.1You will need to fork the approov-flutter-packages if you wish to fix their dependency to a specific tag.
The absinthe_socket package uses a predefined header to forward the Approov Token and also forwards the Approov SDK initialization string to the approov_web_socket package by using a PhoenixChannel socket. The approov_web_socket package interacts with the approov_service_flutter_httpclient by means of an ApproovHttpClient object.
The approov_service_flutter_httpclient package is actually an open source wrapper layer that allows you to easily use Approov with Flutter. This has a further dependency to the closed source Android Approov SDK and iOS Approov SDK packages. Those are automatically added as dependencies for the platform specific targets.
The approov_service_flutter_httpclient package provides a number of accessible classes:
- ApproovServiceprovides a higher level interface to the underlying Approov SDK
- ApproovException, and derived- ApproovNetworkExceptionand- ApproovRejectionException, provide special exception classes for Approov related errors
- ApproovHttpClientwhich is a drop-in replacement for the Dart IO library's- HttpClientand calls the- ApproovService
- ApproovClientwhich is a drop-in replacement for Client from the Flutter http package (https://pub.dev/packages/http) and internally uses an- ApproovHttpClientobject
The following app permissions need to be available in the manifest of your application to be able to use Approov:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />Please read this section of the reference documentation if targetting Android 11 (API level 30) or above.
The approov_service_flutter_httpclient generates a Cocoapods dependency file which must be installed by executing:
pod installin the directory containing the ios project files.
Approov provides a drop in replacement for the Flutter native Http Client. Here is an example of how it can be used in initialization for a the GraphQL client in the HttpLink:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:approov_service_flutter_httpclient/approov_service_flutter_httpclient.dart';
static String _userAuthToken;
static String apiBaseUrl = 'YOUR_API_SERVER_BASE_URL_HERE';
static final approovClient = ApproovClient('<enter-your-config-string-here>');
final HttpLink httpLink = HttpLink(
    uri: apiBaseUrl,
    httpClient: approovClient
);
final AuthLink authLink = AuthLink(
  getToken: () async => _userAuthToken,
);
final Link link = authLink.concat(httpLink);
static ValueNotifier<GraphQLClient> initializeClient(String token) {
    _userAuthToken = token;
    ValueNotifier<GraphQLClient> client = ValueNotifier(
      GraphQLClient(
        cache: OptimisticCache(dataIdFromObject: typenameDataIdFromObject),
        link: link,
      ),
    );
    return client;
}The <enter-your-config-string-here> is a custom string that configures your Approov account access. This will have been provided in your Approov onboarding email.
You may also need to instantiate the AbsintheSocket with an additional parameter in order to support Approov in GraphQL subscriptions over web sockets:
_socket = AbsintheSocket(
      Config.websocketUrl,
      "<your config string here>",
      socketOptions: AbsintheSocketOptions(
          params: {"Authorization": Config.auth_token}),
    );Initially you won't have set which API domains to protect, so the interceptor will not add anything. It will have called Approov though and made contact with the Approov cloud service. You will see logging from Approov saying UNKNOWN_URL.
Your Approov onboarding email should contain a link allowing you to access Live Metrics Graphs. After you've run your app with Approov integration you should be able to see the results in the live metrics within a minute or so. At this stage you could even release your app to get details of your app population and the attributes of the devices they are running upon.
To actually protect your APIs and/or secrets there are some further steps. Approov provides two different options for protection:
- 
API PROTECTION: You should use this if you control the backend API(s) being protected and are able to modify them to ensure that a valid Approov token is being passed by the app. An Approov Token is short lived crytographically signed JWT proving the authenticity of the call. 
- 
SECRETS PROTECTION: This allows app secrets, including API keys for 3rd party services, to be protected so that they no longer need to be included in the released app code. These secrets are only made available to valid apps at runtime. 
Note that it is possible to use both approaches side-by-side in the same app.
See REFERENCE for a complete list of all of the ApproovService methods.