Navigation and App Transport Security with WKWebView

A few disclaimers…I’ve learned that porting over images from Google Docs results in potato quality. My apologies, next time I’ll just send the images separate from my own drafts to self. 😉 I am also figuring out formatting in here, and have concluded that I may need to just use the HTML editor. For now, code samples are in bold and indented. Great things are coming, when it comes to my editing skills, friends.

In iOS versions 9+, we started to have to consider App Transport Security. App Transport Security will block access to any insecure url (starting with “http:”). In order to overcome it, you need to do a couple of things:


You can allow all http:// links to be clickable by adding this:

You should avoid this if at all possible! It completely exposes your site to anything that’s insecure. The only reason I would see doing this if you fully understand that this is risky and you want your users to be able to click on anything they want, essentially using your app as their own mini version of Chrome or Safari.


However, a smarter move is to only allow sites you know are safe. I find it’s acceptable to limit your scope to what your users are most likely to do when interacting with your site(s) and/or partner sites you have direct interaction with. When you’re in an app, it’s expected that the user’s behavior with it will be generally limited to what’s in the expected flow of the app. Let’s say I have an app that uses a webview to show a web app hosted on my server. That app has a link to one of our other sites, but it’s not secure. I’d add that site as shown below.


  1. Add exceptions to your Info.plist file:
    1. Open the Info.plist file from the Solution Explorer.
    2. Navigate to the “Sources” tab.
    3. Under “NSAppTransportSecurity”, expand “NSExceptionDomains”, or add it as a Dictionary item.
    4. Add all domains beneath where you want to be able to access insecure links:

So what do these settings do? From the top:

NSAppTransportSecurity is the group for our custom settings. We then define each URL we’re setting App Transport Security Exceptions for. Anytime we have nested elements, we use the “Dictionary” setting.


NSExceptionAllowsInsecureHTTPLoads is fairly self-explanatory. It allows the webview to load any page that has a “http://…” instead of “https://…” into the web view.

NSAllowsArbitraryLoads – allows all the things on the specified domain to load.

NSIncludesSubdomains – as it says, includes any subdomains the master domain has.

NSExceptionMinimumTLSVersion – by default, Apple requires the server whose site you’re trying to access to have a minimum TLS version of 1.2. If you know you’re connecting to a legacy site/server, you can override the default setting by adding the NSExceptionMinimumTLSVersion. It can be set to 1.0 or 1.1.


There’s other settings you can use when it comes to app transport security. I’ve listed a few links at the end of this article that will describe them.


Hey, cool, you’ve got App Transport Security covered! So technically, you can go to those links now. However, within the WKWebView, you need a NavigationDelegate to help out. If you simply include a NavigationDelegate, you’ll be able to navigate to links in anchors without “target=”_blank’” set. But these days, most of us go to links that are written to open in new tabs. Here’s how you can get your WKWebView to open those links:


Before writing any code, note that Visual Studio will give you an error if you set your target version to anything less than 11. Before you leave your Info.plist file, go to the “Application” tab. Set your target version to 11.0:

Next up, go to the ViewController for the WKWebView:

First, we’re going to add a UIDelegate. It recreates the web view when an external link is clicked on a page viewed within the WKWebView.

Here, when a user wants to navigate to an external page, we have the WKWebView recreate itself, using the url of the link we clicked on. TargetFrame is set to null, because the UIDelegate interprets “target=’_blank” on a HTML anchor as “null”. It works for most of our links, as it’s the trend to open links in a new tab.

public class NavDelegate : WKUIDelegate

        public override WKWebView CreateWebView(WKWebView webView, WKWebViewConfiguration configuration, WKNavigationAction navigationAction, WKWindowFeatures windowFeatures)


            var url = navigationAction.Request.Url;          

            if(navigationAction.TargetFrame == null){



            return null;




That takes care of our view of the new page. We also have to add a NavigationDelegate and DecidePolicy method that will allow navigation to the new page. The UIDelegate let us SEE it, the NavigationDelegate lets us DO it, when it comes to navigating to a new site within the webview.


class AllowAllDelegate : WKNavigationDelegate


        public override void DecidePolicy(WKWebView webView, WKNavigationAction navigationAction, Action<WKNavigationActionPolicy> decisionHandler)






Finally, add a call to the NavigationDelegate from the ViewDidLoad method:


//Instantiate the NavDelegate and UIDelegate after the definition of your webview.
var WebAppView = new WKWebView(View.Frame, new WKWebViewConfiguration());

//lets us navigate using WKWebView

WebAppView.UIDelegate = new NavDelegate();

WebAppView.NavigationDelegate = new AllowAllDelegate();



So now, you can navigate to links. What this doesn’t cover is that you also need a back button, but I wanted to keep the scope of this article limited. Next week, I’ll explore adding a back button to your WKWebView so you can navigate backwards, as well as using gestures to navigate back.


Further Reading:

Apple Developer – UIDelegate

Apple Developer – Navigation Delegate

Stack Overflow – Why is WKWebView not opening links with target=_blank

Use Your Loaf – App Transport Security

Neglected Potential – Working With Apple’s App Transport Security


Leave a Reply