How to Embed Cloudflare Client Certificate and Private Key in a React Native iOS App?

71 views Asked by At

I'm developing a React Native app where my client has provided me with a Cloudflare elliptic curve (EC) type client certificate (certificate.pem) and a private key (privateKey.pem). These certificate are necessary to access APIs, as the server has rules in place to only accept requests with valid certificates.

However, I'm unfamiliar with iOS development and need guidance on how to embed these certificates into my React Native iOS app. My existing iOS code is in Objective C++ e.g (AppDelegate.mm) Can someone provide detailed step-by-step instructions on how to accomplish this? Any insights or code examples would be greatly appreciated.

Thank you!

I tried following things

MyURLSessionDelegate.h

#import <Foundation/Foundation.h>

@interface MyURLSessionDelegate : NSObject <NSURLSessionDelegate>

+ (instancetype)sharedInstance;
- (NSURLSession *)configuredSession;

@end

MyURLSessionDelegate.mm

#import "MyURLSessionDelegate.h"
#import <Security/Security.h>

@implementation MyURLSessionDelegate

+ (instancetype)sharedInstance {
    static MyURLSessionDelegate *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[MyURLSessionDelegate alloc] init];
    });
    return sharedInstance;
}
  
- (NSURLSession *)configuredSession {
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];

    // Load the client certificate
    NSString *pathToCertificate = [[NSBundle mainBundle] pathForResource:@"xyz_certificateName" ofType:@"pem"];
    NSData *certificateData = [NSData dataWithContentsOfFile:pathToCertificate];
  


    if (!certificateData) {
        NSLog(@"Client certificate not found");
        return nil;
    }
    
    // Create a custom SSL configuration with the client certificate
    NSDictionary *sslSettings = @{
        (NSString *)kCFStreamSSLCertificates: @[certificateData],
        (NSString *)kCFStreamSSLValidatesCertificateChain: @NO // Disable certificate chain validation if needed
    };
    
    sessionConfig.TLSMinimumSupportedProtocol = kTLSProtocol1;
    sessionConfig.TLSMaximumSupportedProtocol = kTLSProtocol12;
    sessionConfig.TLSMinimumSupportedProtocol = kTLSProtocol12;
    sessionConfig.TLSMaximumSupportedProtocol = kTLSProtocol13;
    
    sessionConfig.connectionProxyDictionary = sslSettings;
    
    // Create and return NSURLSession with custom configuration and delegate
    return [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
}

#pragma mark - NSURLSessionDelegate Methods

// Implement NSURLSessionDelegate methods as needed

@end

AppDelegate.mm

#import "AppDelegate.h"
#import <Firebase.h>
#import <React/RCTBundleURLProvider.h>
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
#import <TrustKit/TrustKit.h>
#import "MyURLSessionDelegate.h"
#import "SSLPinning.h"
#import "ClientSecurity.h"

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{ 
  
  [FIRApp configure];
  self.moduleName = @“xyz_app";

  self.initialProps = @{};
  UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
  center.delegate = self;

NSURLSession *session = [[MyURLSessionDelegate sharedInstance] configuredSession];
NSLog(@"session configuration: %@", session.configuration);

// Create the URL
NSURL *url = [NSURL URLWithString:@"https://xyz.example.com/rest/login"];

// Create the request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";

// Set the parameters
NSDictionary *parameters = @{@"username": @“example”, @"password": @“Example@123};
NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];

// Set the request body
[request setHTTPBody:postData];

// Set the content type
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

// Create a data task with the session
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    // Check for errors
    if (error) {
        NSLog(@"SS Error: %@", error);
        return;
    }
    
    // Log the raw response data
    NSLog(@"SS Raw Response Data: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    
    // Parse the response data (assuming it's JSON for example)
    NSError *jsonError = nil;
    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
    
    // Check for JSON parsing errors
    if (jsonError) {
        NSLog(@"SS JSON Error: %@", jsonError);
        return;
    }
    
    NSLog(@"SS Response: %@", json);
}];

[dataTask resume];

@end

After implementing above i am getting following result My request is getting blocked by cloudflare.

On api call i'm getting => [AxiosError: Request failed with status code 403]

0

There are 0 answers