0
votes

Background:

I'm upgrading my app to use WKWebview from UIWebview as it will no longer be accepted by App Store

The App Store will no longer accept new apps using UIWebView as of April 2020 and app updates using UIWebView as of December 2020.

Issue:

What happen is, I'm getting cookie return from Webview (WKWebview) after logged in. I will retrieve a token I need for API firing, however I'm constantly hitting HTTP 401 status for all the API(s) fired.

If I revert back to UIWebview, and repeat the same for login but re-using the SAME TOKEN from WKWebview. I'm getting HTTP 200 status. Purpose of re-using same token is to prove that is a valid token.

Noted that, I have not make any changes to the method calling API. It remains the same for both WKWebview and UIWebview. (Including the object request for POST method)

Am I missing something in WKWebview?

Do I need to set cookie or allow anything in specific?

Code snippet:

<WebView
            style={{ width: this.state.webviewWidth }}
            ref={(component) => {
              this.webviewRef = component;
            }}
            source={{ uri: this.state.url }}
            onLoadStart={this.webviewOnLoadStart}
            onLoad={this.webviewOnLoadEnd}
            onNavigationStateChange={this.onNavigationStateChange}
            useWebKit={true}
            sharedCookiesEnabled={true}
          />

Pacakge.json

"react-native": "0.61.5",
"react-native-webview": "^10.3.2",
"@react-native-community/cookies": "^3.0.0",
1

1 Answers

1
votes

Apparently the issue is that WKWebview does not handle cookie passing into the request header for us. Hence I received 401 authentication failure every time when I reach the server.

Unfortunately React-Native-Webview does not has a way to handle this cookie header passing out of the box (Please correct me if I'm wrong). I'm fully aware of this 'custom header' function provided within the lib, unfortunately it didn't work as expected. The cookie is still not part of the request header.

My solution to this is as follow, did under method decidePolicyForNavigationAction:

  1. Dive into native lib (React-Native-Webview)
  2. Loop through all existing cookies within websiteDataStore.httpCookieStore
  3. Look for my cookie (of course, you should know your cookie name)
  4. Append the cookie into the HTTPHeaderField to your http request
  5. Load the http request again!
if (@available(iOS 11.0, *)) {
          [webView.configuration.websiteDataStore.httpCookieStore getAllCookies:^(NSArray<NSHTTPCookie *> * _Nonnull cookies) {
              NSLog(@"All cookies in websiteDataStore %@", cookies);
              for(NSHTTPCookie *cookie in cookies){
                  if([cookie.name isEqualToString:@"coookieName"]){
                      if([navigationAction.request valueForHTTPHeaderField:@"Cookie"] != nil ){
                          
                      }else{
                          NSMutableURLRequest *req = [request mutableCopy];
                          NSString *newCookie = [NSString stringWithFormat:@"cookieName=%@" , cookie.value];

                          // As you can see, I'm appending the cookie value into header myself 
                          [req addValue:newCookie forHTTPHeaderField:@"Cookie"];
                          [req setHTTPShouldHandleCookies:YES];
                          [webView loadRequest:req];
                          return;
                      }
                  }
              }
          }];
      } else {
          // Fallback on earlier versions
      }