19

I developed an app for iOS and Android which accesses an HTML file from my webserver using the in-app browser (Webview).

I don't want that a user can access this file without using the app. Is there a possibility to detect, if the user is accessing the file with the app or directly via a browser on this smartphone / tablet / computer? I think that a solution with PHP is much better, because Javascript can be switched off. At least Google Analytics can differentiate between Safari and Safari (in-app). It should work with every version of iOS and Android.

Thanks for your help.


Solution

After many attempts I finally found a working solution for me!

iOS: You can detect the difference between Safari and the in-app browser using the user agent. Probably there's a nicer solution, but it works.

// Safari (in-app)
if ((strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile/') !== false) && (strpos($_SERVER['HTTP_USER_AGENT'], 'Safari/') == false) {
    echo 'Safari (in-app)';
}

Android: The package name from the app is stored in the PHP variable $_SERVER['HTTP_X_REQUESTED_WITH'].

// Android (in-app)
if($_SERVER['HTTP_X_REQUESTED_WITH'] == "com.company.app") {
    echo 'Android (in-app)';
}

As Tim van Elsloo already noted HTTP headers can be faked and this is not absolutely secure.

ohh2ahh
  • 385
  • 1
  • 2
  • 14
  • iOs solution will fail if the page is opened from other browsers. After some test, I refined it a little. Check here: http://stackoverflow.com/questions/2738766/iphone-webapps-is-there-a-way-to-detect-how-it-was-loaded-home-screen-vs-safar/20757993#20757993 – Francesco Frapporti Dec 24 '13 at 16:16
  • Is this method still valid for IOS11, because in IOS 11, even for in app browser, we are getting back HTTP_USER_AGENT value that contains the word Safari in it. We are getting this: Mozilla/5.0 (iPhone; CPU iPhone OS 11_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.0 Mobile/15E148 Safari/604.1 for in app safari. So I am assuming that this method will no longer work for IOS11? – garfieldmypet Apr 26 '18 at 03:22

3 Answers3

8

I'm not sure about Android, but when you're using the iOS SDK's UIWebView, it sends the name and version of your app as part of the user agent (YourApp/1.0).

You can then use PHP to check if your in-app webview is being used or not:

if (strpos($_SERVER['HTTP_USER_AGENT'], 'YourApp/') !== false)

I think Android does something similar as well.

cutsoy
  • 10,127
  • 4
  • 40
  • 57
  • 1
    Please note that this can obviously be faked by a desktop browser as well (by setting "fake" HTTP headers), so you shouldn't rely on this from a security perspective. – cutsoy May 05 '13 at 11:01
  • 2
    Thanks for your quick help. Unfortunately the user agent does not include the app name. At least not in my attempts. – ohh2ahh May 05 '13 at 12:17
  • Are you using `UIWebView`? It should be something like: `/1.0 CFNetwork/459 Darwin/10.2.0`. If it's not (which I doubt), then you could always try to do something like http://stackoverflow.com/questions/478387/change-user-agent-in-uiwebview-iphone-sdk or http://stackoverflow.com/questions/8487581/uiwebview-ios5-changing-user-agent. – cutsoy May 05 '13 at 12:28
  • 4
    Yes, I'm using UIWebView and I've tried a bit and my app does not appear in the user agent. I even tried it with the iOS simulator from Xcode and only get something like (from the iPhone 6.1 Simulator): Mozilla/5.0 (iPhone; CPU iPhone OS 6_1 like Mac OS X) `AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10B141` Maybe the PHP variable `$_SERVER['HTTP_USER_AGENT']` is not correct? – ohh2ahh May 06 '13 at 13:08
8

Solution code:

$isWebView = false;
if((strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile/') !== false) && (strpos($_SERVER['HTTP_USER_AGENT'], 'Safari/') == false)) :
    $isWebView = true;
elseif(isset($_SERVER['HTTP_X_REQUESTED_WITH'])) :
    $isWebView = true;
endif;

if(!$isWebView) : 
    // Android or iOS Webview
else :
    // Normal Browser
endif;
Kalamarico
  • 5,466
  • 22
  • 53
  • 70
Alex Baur
  • 165
  • 1
  • 2
  • 11
1

For Android WebView, refer the link from Developer Chrome - https://developer.chrome.com/multidevice/user-agent#webview_user_agent

There are already hints available in the user agent string like "Mobile", "wv".

You may use something like

if (strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile') !== false)

or

if (strpos($_SERVER['HTTP_USER_AGENT'], 'wv') !== false)

to detect if the user is an Android WebView.

arjun
  • 1,645
  • 1
  • 19
  • 19