
Show HN: Qeys.io – Web app license validation - frits1993
https://qeys.io
======
DanHulton
Raise your prices.

I can't be alone in thinking that these prices are _insanely_ low when
considering the market. If you're selling to working programmers, $9.99 a
month is a frivolity. I pay more than that for Netflix. For a business
expense? Your $24.99 plan should be the _entry_ point.

You should have a higher tier. A _much higher_ tier, in fact, like $350.
You're targeting agencies and studios at this point. It's still under the
~$500 that requires approval, but there are absolutely businesses out there
that will just sign up for the highest tier they can process, because it's a
status thing or "they may need it". You won't get many signups at this price,
but even one will replace _35_ signups at your current lowest tier. Heck,
more, because higher-priced customers will churn less and require less
support.

Consider dropping your free tier and just relying on your free trial. You're
targeting businesses and working programmers. They have money, so a lack of
money won't be the reason they choose not to use your product, only
product/customer fit.

~~~
ljm
Totally agree on the higher tier, also because there are plenty of things you
will value more just because it charges a higher price. For a freelancer or
agency who needs this because they've been screwed over before, it might even
make the service appear more trustworthy, that you're charging that much
because you are offering security. A few hundred a year is nothing for a bit
of peace of mind and some protection against a client skipping payment and
running off with your code.

Anecdotally, a place I previously worked at raised all of its prices and
tweaked the available plans (with some A/B testing involved) and internally it
was incredibly controversial and made a lot of people unhappy as we were
implementing it. When the testing period was over and all was said and done,
few people complained about the price hikes and far more people either just
accepted it or went for an upgrade.

I think it's very easy for a startup to completely underestimate the value it
provides and assume that nobody would pay more if they had to. But maybe
that's just a bias because you don't tend to hear about the companies that
failed for charging too much. (Not that I would suggest you blindly follow
this advice!)

------
Ruphin
This is nice, but I would never put a piece of code on my property that breaks
the user experience (after a few seconds) when a third party service is
offline. It's even worse because it causes a highly correlated failure vector
across all my products. Imagine your servers going down (for whatever reason)
and _all_ my customers calling me because their websites are broken.

Additionally, defaulting to shutting down the app when it can't reach your
servers breaks all sorts of offline features an app may have.

I would strongly suggest to default to doing nothing when the script can't
contact your servers. Alternatively you let me configure an HTTP endpoint that
will be pinged when it can't reach you so at least I am aware the service is
disrupted.

~~~
frits1993
Hi Ruphin, Frits from Qeys here. I highly appreciate your comment and I
totally agree with what you're saying. Not being able to reach our servers
should not break your app.

The small piece of code is designed to only invalidate and deny access when a
valid response is returned from our servers.

That means that if our service is unreachable you won't be notified about
invalid use, of course, but the app assumes the positive and allows everyone
access until a valid "denied" response.

Did you experience the contrary, or was this simply not clear from what you
read? In that case, I'll try and add that to the FAQ section.

~~~
macca321
Does this mean that they can access the site for free by blocking qeys.io?

~~~
cdurth
From above, it would sound like it O.o

~~~
azeirah
That solution might sound absurd, but what's the alternative? I implemented my
own basic license validation server for an application I wrote, and I ended up
doing the exact same thing.

My server may go down every now and then, I don't want to deny access to the
application just because my 5$/month server is too busy at the moment..

------
aewens
From looking at the JavaScript snippet that is provided, it looks like I can
get around the validation by simply creating a cookie who's contents is
"validated=yes" before the qeys script is loaded.

EDIT: The part of the snippet in question:

    
    
        window.addEventListener('load', function(a){
            document.cookie.indexOf('validated=')<0&&v();
        });

~~~
eat_veggies
I can confirm that this completely stops qeys from even sending a request on
the page I'm testing it on.

However, any client side protection can be bypassed, especially if your
adversary has write access to the code you're trying to protect.

Maybe as an additional protection, qeys should, say, 1 in 7 [0] times, send a
request regardless of whether the cookie present.

[0]
[https://en.wikipedia.org/wiki/Morris_worm](https://en.wikipedia.org/wiki/Morris_worm)

------
theoctopus
This definitely seems like an interesting product, but if you're an anti-
piracy company then maybe you shouldn't be using a pirated font. If you check
the Product Sans CSS file you're including, you'll see there's a notice that
the font is not open source.

~~~
frits1993
Oh wow I had no idea. I simply bought the template from Themeforest, thinking
everything would be in order. Anyway, the font has been changed, well spotted!

~~~
DanHulton
If you bought a template from Themeforest, you may have obtained a license for
the font. If so, no need to change the font. If not, you'd be doing TF a
kindness by letting them know.

~~~
theoctopus
It's Google's special brand font so I doubt they license it. However it is
served from the same domain as Google Fonts so it's an easy mistake to make.

------
drdaeman
From the FAQ section:

> the thief

> the code they just stole

Uh. I know this is extremely widespread to call it so, but copyright
infringement isn't "theft" or "stealing".

~~~
frits1993
Well spotted, thanks. Changed it to pirate.

~~~
drdaeman
Perfect. Bookmarked and will get back to you when I'll purchase a boat. Would
be a nasty surprise to the buccaneers.

~~~
brennebeck
Maybe instead of snark you can recommend what you actually believe to be
valid?

~~~
drdaeman
I really thought that "piracy" comment was a tongue-in-cheek joke (so I had
laughed and played along). I'm sorry if I had offended someone.

As for what it is - I believe I clearly wrote that it's called _copyright
infringement_ (or license violation, or unlicensed use, or unauthorized
copying if you want different wording). And a person is violator, perpetrator,
unauthorized user or something like that (I'm neither a lawyer, nor a native
speaker, I bet one would be able to come with lots of correct terms)

Also, check this out: [https://www.gnu.org/philosophy/words-to-
avoid.en.html#Piracy](https://www.gnu.org/philosophy/words-to-
avoid.en.html#Piracy) and [https://torrentfreak.com/mpaa-banned-from-using-
piracy-and-t...](https://torrentfreak.com/mpaa-banned-from-using-piracy-and-
theft-terms-in-hotfile-trial-131129/)

------
ddtaylor
Seems it would be as effective as cd key protection or DVD protection -
meaning anyone doing the copying likely won't be affected and attempts to
tighten the grip will probably hurt legitimate customers.

~~~
frits1993
You're totally right. However, in the few cases that my software was copied,
the pirates were far from skilled enough to dig into compiled JS and find out
what was happening. At least, they would start with a simple copy-paste and
try to run the copy. If it were to happen again now, I would be notified at
that very moment and I can take action accordingly.

~~~
ddtaylor
Similar to how cd key protection originally was limited to skilled crackers
but as things like SecureRom became normal so did tools that automatically
removed the protection from software.

------
bjpbakker
> by the time the pirate realises that licence validation is in place, it's
> too late for them

> we strongly recommend to let our JavaScript file blend in with the rest of
> your application [..] to make the code responsible for validation as
> difficult as possible to find and break

This smells much more to security by obscurity than an actual licensing
solution.

------
monkeynotes
`[...]make the code responsible for validation as difficult as possible to
find and break` ⌘+W

Seriously though, this seems like an convoluted way for small businesses to
resolve trust issues with their clients.

I mean, if you really want to do this, why not make it incredibly simple and
just ping a server with the domain names the web app is being requested from.
Do it all silently and then let the IP owner decide what to do about it. Why
shut the site down and risk embarrassing, and potential trust destroying,
situations arise from false positives?

~~~
frits1993
"Do it all silently and then let the IP owner decide what to do about it"
sounds like a great idea and could be an application-specific setting. Added
to my to-do list, thanks.

------
fastest963
Their share meta tag is: <meta property="og:title" content="Start.ly — Agency
One Page Parallax Template" />

~~~
frits1993
Ouch. According to facebook debugger, this link has not yet been shared
before, a good thing in this case. Fixed it, thanks.

~~~
bjpbakker
So.. you copied someone's code? /s

~~~
frits1993
Haha no definitely not, the landing page is bought legally from Themeforest ;)

------
eat_veggies
This breaks any existing js that sets window.onload if the qeys script is
loaded after it. Usually it's better to do window.addEventListener('load',
...) so you don't overwrite anything.

~~~
frits1993
Great one, thanks for that!

~~~
frits1993
That's changed now, thanks again.

------
TheGrumpyBrit
"* Unlimited number of lincences"

Also, your privacy policy makes no mention of what data is included with
validation requests, and what you do with that information. GDPR is still very
fresh, and if my app is passing every URL data to a third party, that sounds
like it could be a problem.

~~~
frits1993
Thanks, fixed the typo.

I'll include a section in the privacy policy on what's sent in the request,
which is just the application UUID and the licence key. Our service then uses
the origin of the request to determine the domain.

~~~
teraflop
> I'll include a section in the privacy policy on what's sent in the request,
> which is just the application UUID and the licence key.

And the complete URL of the originating page, as the parent commenter
mentioned.

~~~
teraflop
I just noticed this text in the FAQ:

> Whenever we receive a validation request and grant access, we create a
> fingerprint of the page from which the validation was requested. Then, when
> we deny access to a page which did not provide a (valid) application uuid,
> we try to match the fingerprint of that page with one of the ones we
> indexed. This means that in many cases, we will still be able to notify you
> about invalid use of your application.

Does this mean that your service is collecting not just URLs, but page
contents as well?

------
masukomi
I feel like i'm missing something obvious here. This is for "webapps" which
have been "licensed". Who is running licensed webapps without some form of
user account? Either a login or an API key, which can easily be turned off if
the person stops paying. If i have that, why do i need this? If i don't have
that, haven't i just totally fallen down on the job of controlling access to
my system?

What am i missing here?

~~~
albertgoeswoof
It's for on-premise deployments, where you don't have control over the
deployment environment.

~~~
masukomi
thanks @albertgoeswoof

"The small piece of code is designed to only invalidate and deny access when a
valid response is returned from our servers." seems pretty easy to circumvent
but... i guess you could make your app stop working if it fails to get a
response within x days or whatever, but you'd have to use a compiled language
to make that even remotely difficult to not circumvent too.

~~~
theoctopus
I think the primary purpose is the notifications, not the blocking. Even if
they browse to the page once, see the block and disable it, you'll still know.

------
SimeVidas
I am so confused.

> Besides, we strongly recommend to let our JavaScript file blend in with the
> rest of your application's JavaScript. Webpack, compress and uglify the best
> you can, to make the code responsible for validation as difficult as
> possible to find and break.

Ok, so this is a solution to _detect_ (some of) the sites that use your
JavaScript code without approval, not a solution to prevent them from doing it
(since it can be easily blocked once you _know_ to look for it).

~~~
frits1993
Exactly. By detecting and letting you know what happened, you'll be able to
take action. You know who you built the application for and will most likely
still have their phone number which you can use to ask them what's going on.

------
madeofpalk
_> The instant solution to worrying less about your web applications being
copied by the clients you developed them for._

Is this a problem that happens often?

~~~
frits1993
The problem of my clients actually copying my software: no. The problem of
being worried about it: yes

On a serious note, it has happened to me a handful of times in many years. Not
often, but enough times to want to be notified when it happens again.

------
beefhash
See also: [https://keygen.sh/](https://keygen.sh/)

------
sshine
Question: How about having the option of not blocking but only reporting?

Then you can put a use clause in your service agreement and bill your
customers according to their use. They've signed that any additional use
incurs a cost, but they don't think you know.

~~~
frits1993
Definitely, monkeynotes had a similar suggestion so with your comment on top
of that, this is definitely on my to do list.

------
someusrrrr22
Why not just do `if(window.location.href !== '[http://our-
site.com'](http://our-site.com')) { send_email(window.location.href + ' stole
code'); }`?

~~~
vortico
I think this is for local deployments of web apps like a localhost site or
Electron app. I could be wrong though.

------
eat_veggies
It would be nice to have some copy/pasteable snippets to integrate this with
my stuff. It is unclear what I should do once I register an application and am
presented with a list of keys.

~~~
frits1993
Next to every key there is a button with a question mark "how to use", which
presents a pop-up with a copy/pasteable snippet.

------
cphoover
in my mind the only true way to protect against client software ripping is to
put all of the protected IP on your service, and make service calls to it from
the client application. If the code resides on their hardware... there aint
really anything you can do to protect it.

------
Marysville
`location.hostname!='www.clientdomain.com'?document.body.innerHTML=''`

------
stevekemp
Minor typo on your front-page "deativate" rather than "deactivate".

~~~
frits1993
Thanks, fixed it!

~~~
sambeau
Also, lincences

    
    
      "Unlimited number of lincences"

------
pixsil
Pretty nice! I like your tool, definitely going to try it

------
eat_veggies
would it be possible to steal a website's code, then tack on a service worker
that intercepts requests to qeys?

~~~
teraflop
Sure, but as other commenters have mentioned, if you were going to go to that
trouble you could just remove the license check code.

I guess a service worker has the advantage of not having to dig through
potentially obfuscated Javascript code. But it's not like that would be hard
to do, given that Chrome's debugging tools record a stack trace for every
XMLHttpRequest.

------
jlebrech
0.0.0.0 qeys.io

~~~
bjpbakker
That won't really work for the scenario they try to "protect" against.

When you copy some js files that include their license checking code to your
server and them serve it to your clients, your clients need to block qeys.io,
not you.

You can instruct clients to do that of course, but it's rather easy for one of
them to forget and the copyright holder is noticed.

Still, blocking qeys.io by default on your system sounds like a good idea :)

~~~
ake1
if it's for internal use, you most likely have access to the DNS-server the
clients are using, not an unlikely scenario when it comes to licensed code
like this i would imagine.

------
jlebrech
What's even better is to have a backend that side a payload to the client when
events are triggered, so no js is loaded in advance.

~~~
dawnerd
Was hoping they'd just have an api you could check against, maybe op could do
that pretty easily since the frontend is already making a request.

~~~
frits1993
Yes you can definitely do that. The /validate endpoint accepts the parameters
application (for the application uuid) and the key (for licence key). You can
program your way around that, but the one line solution then does not hold up.

