From b9b6fd26b9cee1cdd0a45cba4b37444c3b2f4907 Mon Sep 17 00:00:00 2001 From: "kefah@Cocarz" Date: Mon, 17 Feb 2020 16:16:58 +0100 Subject: [PATCH 1/3] Keeping response standard between AFSuccess and AFFailure --- src/https.ios.ts | 61 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/src/https.ios.ts b/src/https.ios.ts index 2f9cf33..f398629 100644 --- a/src/https.ios.ts +++ b/src/https.ios.ts @@ -59,27 +59,48 @@ function AFSuccess(resolve, task: NSURLSessionDataTask, data: NSDictionary & NSData & NSArray = error.userInfo.valueForKey(AFNetworkingOperationFailingURLResponseDataErrorKey); + let content: any; + if (data && data.class) { + if (data.enumerateKeysAndObjectsUsingBlock || (data) instanceof NSArray) { + let serial = NSJSONSerialization.dataWithJSONObjectOptionsError(data, NSJSONWritingOptions.PrettyPrinted); + content = NSString.alloc().initWithDataEncoding(serial, NSUTF8StringEncoding).toString(); + } else if ((data) instanceof NSData) { + content = NSString.alloc().initWithDataEncoding(data, NSASCIIStringEncoding).toString(); + } else { + content = data; + } - let reason = error.localizedDescription; - resolve({task, content, reason}); + try { + content = JSON.parse(content); + } catch (e) { + } + } else { + content = data; + } + /*let body = NSString.alloc().initWithDataEncoding(data, NSUTF8StringEncoding).toString(); + try { + body = JSON.parse(body); + } catch (e) { + } + let content: any = { + body, + description: error.description, + reason: error.localizedDescription, + url: error.userInfo.objectForKey('NSErrorFailingURLKey').description + }; + */ + let failure: any = { + body: content, + description: error.description, + reason: error.localizedDescription, + url: error.userInfo.objectForKey('NSErrorFailingURLKey').description + }; + if (policies.secured === true) { + failure.description = 'nativescript-https > Invalid SSL certificate! ' + error.description; + } + let reason = error.localizedDescription; + resolve({task, content, reason, failure: failure}); } export function request(opts: Https.HttpsRequestOptions): Promise { From 644f778385f2de2cc2a5d4b303ea158bc1ab069d Mon Sep 17 00:00:00 2001 From: "kefah@Cocarz" Date: Wed, 19 Feb 2020 19:27:10 +0100 Subject: [PATCH 2/3] Add useLegacy to HttpsSSLPinningOptions --- src/https.common.d.ts | 29 +++++++++++ src/https.common.ts | 2 + src/https.ios.ts | 110 ++++++++++++++++++++---------------------- 3 files changed, 83 insertions(+), 58 deletions(-) create mode 100644 src/https.common.d.ts diff --git a/src/https.common.d.ts b/src/https.common.d.ts new file mode 100644 index 0000000..f2f9bac --- /dev/null +++ b/src/https.common.d.ts @@ -0,0 +1,29 @@ +import { Headers } from 'tns-core-modules/http'; +export interface HttpsSSLPinningOptions { + host: string; + certificate: string; + allowInvalidCertificates?: boolean; + validatesDomainName?: boolean; + commonName?: string; + useLegacy?: boolean; +} +export interface HttpsRequestObject { + [key: string]: string | number; +} +export interface HttpsRequestOptions { + url: string; + method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD'; + headers?: Headers; + params?: HttpsRequestObject; + body?: HttpsRequestObject; + allowLargeResponse?: boolean; + timeout?: number; +} +export interface HttpsResponse { + headers?: Headers; + statusCode?: number; + content?: any; + reason?: string; + reject?: boolean; + failure?: any; +} diff --git a/src/https.common.ts b/src/https.common.ts index 99e17cd..f23c0ad 100644 --- a/src/https.common.ts +++ b/src/https.common.ts @@ -6,6 +6,7 @@ export interface HttpsSSLPinningOptions { allowInvalidCertificates?: boolean; validatesDomainName?: boolean; commonName?: string; + useLegacy?: boolean; } export interface HttpsRequestObject { @@ -36,4 +37,5 @@ export interface HttpsResponse { content?: any; reason?: string; reject?: boolean; + failure?: any; } diff --git a/src/https.ios.ts b/src/https.ios.ts index f398629..a46cbd2 100644 --- a/src/https.ios.ts +++ b/src/https.ios.ts @@ -7,6 +7,8 @@ interface Ipolicies { secure?: AFSecurityPolicy; } +let useLegacy: boolean = false; + let policies: Ipolicies = { def: AFSecurityPolicy.defaultPolicy(), secured: false, @@ -23,6 +25,7 @@ export function enableSSLPinning(options: Https.HttpsSSLPinningOptions) { let data = NSData.dataWithContentsOfFile(options.certificate); policies.secure.pinnedCertificates = NSSet.setWithObject(data); } + useLegacy = (isDefined(options.useLegacy)) ? options.useLegacy : false; policies.secured = true; console.log('nativescript-https > Enabled SSL pinning'); } @@ -35,72 +38,41 @@ export function disableSSLPinning() { console.info('nativescript-https > Disabled SSL pinning by default'); function AFSuccess(resolve, task: NSURLSessionDataTask, data: NSDictionary & NSData & NSArray) { - let content: any; - if (data && data.class) { - if (data.enumerateKeysAndObjectsUsingBlock || (data) instanceof NSArray) { - let serial = NSJSONSerialization.dataWithJSONObjectOptionsError(data, NSJSONWritingOptions.PrettyPrinted); - content = NSString.alloc().initWithDataEncoding(serial, NSUTF8StringEncoding).toString(); - } else if ((data) instanceof NSData) { - content = NSString.alloc().initWithDataEncoding(data, NSASCIIStringEncoding).toString(); - } else { - content = data; - } - - try { - content = JSON.parse(content); - } catch (ignore) { - } - - } else { - content = data; - } - + let content = getData(data); resolve({task, content}); } function AFFailure(resolve, reject, task: NSURLSessionDataTask, error: NSError) { let data: NSDictionary & NSData & NSArray = error.userInfo.valueForKey(AFNetworkingOperationFailingURLResponseDataErrorKey); - let content: any; - if (data && data.class) { - if (data.enumerateKeysAndObjectsUsingBlock || (data) instanceof NSArray) { - let serial = NSJSONSerialization.dataWithJSONObjectOptionsError(data, NSJSONWritingOptions.PrettyPrinted); - content = NSString.alloc().initWithDataEncoding(serial, NSUTF8StringEncoding).toString(); - } else if ((data) instanceof NSData) { - content = NSString.alloc().initWithDataEncoding(data, NSASCIIStringEncoding).toString(); - } else { - content = data; + let parsedData = getData(data); + if (useLegacy) { + let failure: any = { + body: parsedData, + description: error.description, + reason: error.localizedDescription, + url: error.userInfo.objectForKey('NSErrorFailingURLKey').description + }; + if (policies.secured === true) { + failure.description = 'nativescript-https > Invalid SSL certificate! ' + error.description; + } + let reason = error.localizedDescription; + let content = parsedData; + resolve({task: task, content: content, reason: reason, failure: failure}); + } else { + let content: any = { + body: parsedData, + description: error.description, + reason: error.localizedDescription, + url: error.userInfo.objectForKey('NSErrorFailingURLKey').description + }; + + if (policies.secured === true) { + content.description = 'nativescript-https > Invalid SSL certificate! ' + content.description; } - try { - content = JSON.parse(content); - } catch (e) { - } - } else { - content = data; - } - /*let body = NSString.alloc().initWithDataEncoding(data, NSUTF8StringEncoding).toString(); - try { - body = JSON.parse(body); - } catch (e) { - } - let content: any = { - body, - description: error.description, - reason: error.localizedDescription, - url: error.userInfo.objectForKey('NSErrorFailingURLKey').description - }; - */ - let failure: any = { - body: content, - description: error.description, - reason: error.localizedDescription, - url: error.userInfo.objectForKey('NSErrorFailingURLKey').description - }; - if (policies.secured === true) { - failure.description = 'nativescript-https > Invalid SSL certificate! ' + error.description; + let reason = error.localizedDescription; + resolve({task, content, reason}); } - let reason = error.localizedDescription; - resolve({task, content, reason, failure: failure}); } export function request(opts: Https.HttpsRequestOptions): Promise { @@ -180,3 +152,25 @@ export function request(opts: Https.HttpsRequestOptions): Promisedata) instanceof NSArray) { + let serial = NSJSONSerialization.dataWithJSONObjectOptionsError(data, NSJSONWritingOptions.PrettyPrinted); + content = NSString.alloc().initWithDataEncoding(serial, NSUTF8StringEncoding).toString(); + } else if ((data) instanceof NSData) { + content = NSString.alloc().initWithDataEncoding(data, NSASCIIStringEncoding).toString(); + } else { + content = data; + } + + try { + content = JSON.parse(content); + } catch (e) { + } + } else { + content = data; + } + return content; +} \ No newline at end of file From 07653e848685b5a3c61b30ec862e2d0fff2c2a1d Mon Sep 17 00:00:00 2001 From: "kefah@Cocarz" Date: Thu, 20 Feb 2020 09:15:12 +0100 Subject: [PATCH 3/3] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4c68159..c2c224c 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,7 @@ Option | Description `certificate: string` | The uri path to your `.cer` certificate file. `allowInvalidCertificates?: boolean` | Default: `false`. This should **always** be `false` if you are using SSL pinning. Set this to `true` if you're using a self-signed certificate. `validatesDomainName?: boolean` | Default: `true`. Determines if the domain name should be validated with your pinned certificate. +`useLegacy?: boolean` | Default: `false`. [IOS only] set to true in order to get the response data (when status >= 300)in the `content` directly instead of `response.body.content`. ## Webpack / bundling Since you're probably shipping a certificate with your app (like [our demo does](https://github.com/EddyVerbruggen/nativescript-https/tree/master/demo/app/assets)),