Device detection NOT based on UA - javascript

I'm looking to restrict the use of my webapp for handheld devices only, and completely disable for desktop.
There're a ton of libraries available for device detection, but all of the sniff User-Agent which can easily be faked. Is there any library that goes beyond UA and uses other checks to make sure the device is indeed a handheld?

Not sure if it would be helpful, but I would like to address your question in two sections:
I'm looking to restrict the use of my webapp for handheld devices
only, and completely disable for desktop.
Well, that is technically not feasible because of the reasons mentioned by #guest271314 (and other comments). Moreover, there are many software applications whose only task is to simulate a mobile environment on desktop devices and almost all of them make use of UA sniffing. Moving back to your second query,
Is there any library that goes beyond UA and uses other checks to make
sure the device is indeed a handheld?
If you want to know about the nature of browsers and devices accessing your services, there are a few different approaches to this task:
User-Agent Sniffing
Feature Detection
Device Detection
Now unfortunately, some confuse these at times. Yet each of these approaches to discover properties of the HTTP client works differently and, above all, they often play different roles in the technology stack.
User-Agent Sniffing
With "User-Agent Sniffing" (UA Sniffing), one can derive properties of the client by looking at the User-Agent header in the HTTP request. UA Sniffing usually involves searching for a specific string or pattern in the UA string and basing choices on the result of that search. While UA Sniffing can be done with JavaScript on the client itself, nothing prevents people from performing UA Sniffing on the server. UA sniffing also have some downfalls. First one is: going down the slippery slope of constantly updating your sites and services to follow the never-ending evolution of the browser and device market. Secondly, UA can also be faked(as you mentioned in your post).
Feature Detection
Its the approach where we don’t test the User-Agent string but rather, we test for features that a browser claims to support. Feature detection is about checking for certain functions or features of the browser using JavaScript. Seeing the context of your query, this is what you might be looking for.
Feature Detection also has downsides. The most deadly one is called “false positives”. For example, your test of the browser tells you “yes, I support this feature! Fire away!”, only to discover that Geolocation is not really supported.
The most common tool for Feature Detection is Modernizr.
Device Detection
Device Detection is about having a framework that maps HTTP requests to the full profile of mobile device properties, including properties that relate to browsers and OSes. It happens on the server typically and has the added advantage of sending only content and formats that client can easily parse and use to the browser.
Some tend to confuse UA-Sniffing with Device Detection. In fairness to those, Device Detection does exploit analysis of the HTTP request (and the User-Agent string particularly) to operate. But the similarity ends there. A fully-fledged device detection framework, such as WURFL, will go out of its way to avoid false positives and above all, it will return device properties and capabilties that cannot be derived by UA analysis.
Hope it helps

I'm looking to restrict the use of my webapp for handheld devices
only, and completely disable for desktop.
Abandon all hope. This is not possible. For example, an RDF application at the "handheld" could be accessed by separate "desktop" computer. Even if access were successfully restricted to "handheld devices" access to the device hardware , software may, or may not be simultaneously restricted, allowing the "handheld" operating system , browsers, display, etc. to be viewed at a local or remote "desktop".
adb , or similar interfaces for non-android platforms could also access "real-time", or saved html ,js viewed at "handheld" device - at "desktop".

In brief - there's no reliable way for a server to tell which devices initiates communication with it. Everything in the HTTP headers/content can be spoofed with the simplest script.
In the client side things are even more open so - naturally any client side code can be viewed, extracted, manipulated, changed and used in any way a skilled developer would like.
But you can try to make life a bit harder for the hacker, my best shot in client side would be to use a few checks using Javascript and Modernizr to detect touch devices and then try to distinguish between these and desktop devices that support touch.
So:
1) Detect only touch devices through Modernizr.touch, docs here: http://modernizr.com/docs/
It's a client side javascript to detect touch devices.
2) To rule out desktops I would test if the device width is smaller than 1024 (javascript: screen.width) . Most handheld devices width are such.
3) Maybe the only popular exception for that exception for this would be iPads. They have 1024px device width, just like some desktops with touch support. In this case you could use user agent check in client side (that's a little harder to spoof than the user agent sent to the server in HTTP but still possible)
isiPad = navigator.userAgent.match(/iPad/i) != null;
Then I'd minimize everything to make it somewhat harder to manipulate and hack, so the average user hopefully won't bother, or won't have the skills to break this, and hope for the best.

Related

Is there a foolproof way to check browser in JS or Node.JS?

I have a website where I want to ban all users not using a chrome and derivatives, firefox and derivatives, safari, or a new version of opera (IE and other old browsers may compromise security). Is there an absolutely foolproof way (so that even a hacker couldn't spoof their browser) to do this in JavaScript on the client or server side?
No, it can't be done reliably. You could use some complex JavaScript timing runs and compare the time to execute for the bank of tests against the known timings for each browser and version. Obviously this would have to be tested on a ratio basis to rule out differences in hardware performance. This would not, however, be foolproof and would require "fingerprinting" performance for every single browser version and make that you will accept and would need to be constantly updated as each new browser version was released. This is not a foolproof method and is generally considered a very bad idea. It can also result in false positives which will cause people with compliant browsers to be denied access based on variability in your JavaScript fingerprinting tests.
Hardening your server is a much better way to go and using simple browser identifiers like navigator name will provide the results you need. The trouble with trying to design a foolproof method is that, even if you get it to work, a cagey hacker can still get you. Hardening the Server is the only real way to secure your site.
This is a terrible security method
You should not be banking on the fact that a user is visiting your site from a particular browser. You should instead choose to either allow functionality to those compliant browsers and disable it to others via signatures (the part the browser sends which helps identify the particular browser type).
Most importantly, you should never leave a vulnerability in your application! If you know it's a vulnerability in different browser types, fix the problem - don't try to hide it. People will always find a way around a hidden problem. Easy fix? Make it so there is no problem to hide!

JavaScript: How to determine performance of the runtime (aka browser)?

I have a JavaScript application, which works fine, but certainly needs some memory / CPU performance (it is based on top of Google maps).
So basically it runs fine on a Desktop / Laptop PC, iPad works OK. But with all these different devices nowadays, smaller devices are definitely overloaded.
So basically I want to determine the available runtime and decide whether I start my JavaScript application, or display a message instead.
OK, I could check the browser, but this is a never ending story
I could check on the OS information, but again this is very tedious. Also some OS run on high performance devices as well as low end hardware.
I could check on the screen size and rule out mobile phones, but then it gets difficult
So is there a way to determine the performance of the client? Just to make it clear, I do not care whether it is a tablet for instance, but if it is a low performance tablet with little CPU performance / memory (so Detect phone/tablet/web client using javascript does not help).
In javascript You could check list of features and based on that do conclusion if device is low memory.
For example:
Check core count with window.navigator.hardwareConcurrency
(For better coverage add Core Estimator polyfill)
Check WebGL support (I like user2070775 suggestion): Proper way to detect WebGL support?
Check if its desktop or mobile. Most likely desktop will not have any problems with memory.
Check resolution of screen - most likely small resolution will be on low memory devices.

Is there a way to determine if a Javascript client is using a phone on a mobile network as opposed to wifi?

I'm trying to make a site as responsive as possible for phone users, and that means removing several bandwidth-hungry features. In particular, I'd like to load an external font if the user is on wifi but not on 3g/4g.
A pretty good proxy for this is 'phone or tablet', with tablets usually being the cutoff for 'good connection'. This kinda works, but there are 3g/4g tablets, and there are phones on wifi, so it's not perfect.
I don't think it's possible to get this any better, but perhaps stackoverflow's collective wisdom has discovered a way. Is this detectable?
Rather than focusing on mobile or not, just do a bandwidth test. The only way to really be sure is measure the time to download a file to their device.
Try the accepted answer here: How to detect internet speed in Javascript?
You can try the solution suggested in this answer, that is to use navigator.connection.type. However, this is definitely non-standard and it seems to be limited to Android devices only. Also, see the MDN entry, which mentions a metered property on the same navigator.connection object - this may also be useful.
For the best coverage: var connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
The only way to do this I know of, which has it's own problem, is to do a reverse lookup on the IP address of the request at the time of the request (on the web server) and see if it's from a Wireless Carrier. The two problems with this are; that I don't know if mobile devices use a different network than say wired networks (Version Wireless vs Version Fios), and the other problem is employees of those companies who may actually be wired will appear wireless.
You could try doing a network probe for very common local addresses (only reachable over Wifi), such as 192.168.1.100 and friends. Here's how:
Create an img element with an onError handler.
Set the src property to the address you want to "ping"
If you get an error, then you know the address does not exist
No error means the address exists
I initially read about this technique in Ajax Security (great book).
JavaScript does not provide any hooks into network-level connection types. The best you can do is time the download of a known test file and decide based on that.
If that fails, just ask the user if they prefer the high/low bandwidth setting.

jQuery IF statement (Only if a web browser on a desktop) not a mobile device / iPad

is there a easy way with jQuery to essentially have a jQUery/JS if statement along the lines of:
IF User is on a web Browser on a desktop... not a mobile device / iPad
Thanks
Although not really recommended to use this, here it is:
http://api.jquery.com/jQuery.browser/
excerpt:
Because $.browser uses navigator.userAgent to determine the platform, it is vulnerable to spoofing by the user or misrepresentation by the browser itself. It is always best to avoid browser-specific code entirely where possible. The $.support property is available for detection of support for particular features rather than relying on $.browser.

Possible to detect the *type of mobile device* via javascript or HTTP Headers?

I've got a request from a customer to automatically detect the type of mobile device (not the browser, the type. ex: Moto Q, Blackjack II, etc.) and automatically select the device from a drop down with a list of supported devices.
So far I've found that the HTTP Headers (submitted by mobile IE) contain information such as
Resolution
UA-CPU (i've seen ARM from WM 2003 and x86 from WM5)
User Agent (which basically just says Windows CE)
The only thing I can think of right now is possibly using a combination of the resolution/cpu and making a "best guess"
Any thoughts?
You may want to have a look at WURFL, here: http://wurfl.sourceforge.net/.
From the site:
So... What is WURFL?
The WURFL is an XML configuration file which contains information about capabilities and features of many mobile devices.
The main scope of the file is to collect as much information as we can about all the existing mobile devices that access WAP pages so that developers will be able to build better applications and better services for the users.
What exactly does the customer mean by "supported". Surely it means that the phone in question supports the web application and it's inner functionality - wouldn't it be better then to forget device detection and simply focus on detecting those capabilities required for the app to function properly? For example, if my mobile website requires Ajax to work then instead of listing all the devices which are said to "support Ajax" I could do some simple object detection to find out for myself.
Device detection, just like browser detection is unreliable. Yes, it's possible but I wouldn't recomend it... on a project I've done we used the User Agent string to detect various devices. The indexOf javaScript method came in handy! :)
Another fast and easy solution is Apache Mobile Filter: http://www.apachemobilefilter.org

Categories