How to implement mTLS with ApolloClient in ReactNative?

I have a requirement to achieve mTLS with ApolloClient in ReactNative. Any inputs on the same?

You can read about mTLS here - https://www.cloudflare.com/learning/access-management/what-is-mutual-tls/

@JeffAuriemma Hi Jeff, thanks for updating the tag. However, since I am using react-native, I am trying to implement this for a mobile app. I would appreciate if you could add the mobile tag back. Also, any recommendations on resolving this challenge? Thank you!

Hi @rakmo :wave: apologies for the confusion. The mobile tag is for Apollo iOS and Apollo Kotlin posts. Though you’re developing for React Native, your inquiry regards the TypeScript Apollo Client which we call web. Hope that clears things up :slight_smile: I’m planning to address your initial question soon!

1 Like

Hi @JeffAuriemma - I would really appreciate if any updates on this or if would be great if you could mention the ETA. Thank you!

Hi @rakmo :wave: thanks for the reminder, I am so sorry for letting this fall off my radar! I am unfamiliar with mTLS but I did ask an LLM instance trained on Apollo Client for some ideas. The following is the output I got. I briefly checked it for hallucinations and it looks legit but still, use caution and vet this very carefully before investing too deeply:


(begin LLM-generated content)

To implement mTLS with Apollo Client in a React Native application, you can follow these steps:

  1. Configure React Native’s networking layer to use mTLS:You can use a library like react-native-pinch or react-native-tls to configure the networking layer of your React Native application to support mTLS.
  2. Create a custom link for Apollo Client:Instead of using the default HttpLink, create a custom link with the necessary parameters for the mTLS configuration in your React Native application. You can utilize the fetch function that supports mTLS from one of the libraries mentioned above to create a custom fetch function.
  3. Pass the custom fetch function to Apollo Client’s link:Use the custom fetch function as a parameter when creating the HttpLink for the Apollo Client. This ensures that the client uses the mTLS-enabled fetch function for communication with the server.

Here’s an example using react-native-pinch:

// apolloClient.js
import { ApolloClient, InMemoryCache, HttpLink } from "@apollo/client";
import RNPinch from "react-native-pinch";

// Custom fetch function with mTLS support
const customFetch = (uri, options) => {
  const { method, body, headers } = options;
  const requestData = {
    method,
    body,
    headers,
    // Include your client and CA certificates for mTLS
    clientCert:
      "-----BEGIN CERTIFICATE-----\nYOUR_CLIENT_CERTIFICATE\n-----END CERTIFICATE-----",
    clientKey:
      "-----BEGIN PRIVATE KEY-----\nYOUR_CLIENT_PRIVATE_KEY\n-----END PRIVATE KEY-----",
    caCert:
      "-----BEGIN CERTIFICATE-----\nYOUR_CA_CERTIFICATE\n-----END CERTIFICATE-----",
  };
  return RNPinch.fetch(uri, requestData).then((response) => {
    const reader = response.body.getReader();
    const headers = new Headers(response.headers);
    return reader
      .read()
      .then(({ value }) => ({
        ok: response.ok,
        status: response.status,
        statusText: response.statusText,
        url: response.url,
        clone: response.clone,
        headers,
        arrayBuffer: () => Promise.resolve(value),
        blob: () => Promise.reject(new Error("blob not supported")),
        formData: () => Promise.reject(new Error("formData not supported")),
        json: () => Promise.resolve(JSON.parse(value)),
        text: () => Promise.resolve(value.toString()),
      }));
  });
};
const httpLink = new HttpLink({
  uri: "https://your-api-endpoint/graphql",
  fetch: customFetch,
});
const client = new ApolloClient({ link: httpLink, cache: new InMemoryCache() });
export default client;

In this example, we are using the react-native-pinch library to handle the mTLS connection. We define a custom fetch function called customFetch, which uses the RNPinch.fetch() method to send requests over an mTLS connection. The customFetch function is then passed as a parameter while creating the HttpLink in the Apollo Client configuration, thereby ensuring that the client uses the mTLS-enabled fetch function for communication with the server.By following these steps and using an appropriate library, you can implement mTLS with Apollo Client in a React Native application. This allows you to secure the communication between your Apollo Client and the GraphQL server by verifying the TLS certificates of both parties, ensuring a more secure and encrypted connection. Note, however, that mTLS implementation might vary depending on the specific networking libraries and React Native versions you use. Make sure to consult the documentation of the libraries you choose and adapt the configuration accordingly to ensure a successful mTLS setup in your application.

(end LLM-produced content)


I hope this points you in the right direction :pray: I’d be eager to hear from you to see if this approach was productive.

@rakmo any progress?

  1. Generate or obtain the required client and server certificates and keys.
  2. Install the required dependencies for mTLS in your React Native project, such as the axios library.
  3. Configure your server to require client authentication with mTLS.
  4. Configure your ApolloClient instance to use mTLS by passing the client certificate, client key, and CA certificate to the httpsAgent option of the createHttpLink function.
  5. Use the configured ApolloClient instance to make requests to the server.

Here’s an example code snippet to configure ApolloClient with mTLS:

import { ApolloClient, InMemoryCache } from '@apollo/client';
import { createHttpLink } from 'apollo-link-http';
import axios from 'axios';
import fs from 'react-native-fs';

// Read the client certificate and key from files
const clientCert = fs.readFileSync('/path/to/client/cert');
const clientKey = fs.readFileSync('/path/to/client/key');

// Create an axios instance with the client certificate and key
const axiosInstance = axios.create({
  cert: clientCert,
  key: clientKey,
});

// Create an HttpLink with the axios instance and server URL
const httpLink = createHttpLink({
  uri: 'https://example.com/graphql',
  fetch: (uri, options) => axiosInstance({ url: uri, ...options }),
});

// Create an ApolloClient instance with mTLS enabled
const client = new ApolloClient({
  link: httpLink,
  cache: new InMemoryCache(),
  httpsAgent: new https.Agent({
    cert: clientCert,
    key: clientKey,
    ca: fs.readFileSync('/path/to/ca/cert'),
  }),
});
Note that this is just an example, and the specific implementation details may vary depending on your server and client configurations. It's also important to ensure that your certificates and keys are kept secure and not exposed to unauthorized parties.






Hi @mkdangi21, can you help us understand the httpsAgent option you passed to the ApolloClient constructor? That’s not a property that’s used in the client.

Does any of these solutions work? I could not get these working in react-native mobile application with mTLS.