2

From my previous question: How secure is this schema between a Desktop App (c++) and an API (php).


Introduction

I made a paid Desktop-app that required constant internet connection (because of its nature, not because of security or this schema). Because this is an specific situation I decided to design my own schema.

My lack of knowledge (I'm an student and I've been programming Desktop Apps for like 3 years, all of those free without any kind of internet connection) led me to make bad / insecure schemas that affected user experience or had some serious flaws. After doing A LOT of research I designed a lot more and found flaws on all of them until I came with this one.

But why open a question on StackExchange? On this schema I use JWT to solve most of my problems (data signing, dynamic answers, etc.) but because of my knowledge I'm not able to tell if it is secure or not and if it's a good implementation.


About the Schema

Normal Workflow:

Client logs in using the Desktop App (and receives a JWT) and every X seconds/minutes the Desktop App sends this JWT to see if it's still valid. My questions are probably simple but couldn't be answered using google.

No browser is involved, everything is done between the Desktop App sending POST requests and the API answering.

I have 2 .php files:

  • check.php: it's the one that receives the Requests every X seconds/minutes.
  • login.php: used once to log in everytime the user opens the Desktop App.

Login.php

Receive username, password and a random value. Check if username and password are okay, then generate and store in DB a JWT using random value + SharedSecret_1 . Send the JWT back to the Desktop App so it can check if it's valid and proceed to let the user use the software.

Check.php

Receive a JWT and a random value. Check if the JWT is the same than the one in the DB then generate and store in DB a new JWT using random value + SharedSecret_2. Send the JWT back to the Desktop App so it can check if it's valid.


I had 4 main problems:

  1. How to make sure the Desktop App knows if the JWT it receives is valid and not faked by the user.
  2. How to make sure the API knows if the data sent by the Desktop App is valid and not faked.
  3. The API needs to send a unique JWT everytime because if it's always "Y" then user would be able to forward the data send by the Desktop App and fake an answer "Y".
  4. I don't want multiple users using the same account at the same time. Only 1 connection per account. (Like in an online game were if someone logs in while you are logged in, you get kicked).

From the answer I came with this idea:

  • Solution for 1st problem: Both Desktop App and API share a Secret Key that the API will use to generate the JWT and the Desktop App will use to verify this JWT.
  • Solution for 2nd problem: Desktop App signs data before sending it.
  • Solution for 3rd problem: A random value is sent by the Desktop App (along the JWT) everytime it performs the checks so the API uses it to generate a different JWT.
  • Solution to 4th problem: Using different SharedSecrets for "login" and "check", If a user forwards the checks to the login, it will generate a token with SharedSecret_1 and when the Desktop App verifies this token it will use SharedSecret_2 (because that's what's used for check.php) making it invalid.

My questions are:

  • From Solution to 2nd problem (client-side data signing):

    1. When the Desktop App sends the data, is it secure to "sign" it generating a JWT on the client-side and verifying it on the API using a Shared Secret? Or should I use RSA with public/private key pair?.
  • From Solution to 3rd problem (random value on JWT):

    1. Can this random value be known by anyone without risking security? (Because the user would still need the shared secret to be able to generate a valid JWT)
    2. Should the random value be sent inside the JWT?
    3. How "random" should this value be? Is it okay if it's a simple number from 1 to 100000?
  • General:

    1. Is this approach secure enough to be implemented? I know how secure are JWT but maybe MY implementation makes it non-secure.

When I'm asking about security I mean against piracy, preventing users from accessing my paid app for free. (I know it can't be 100% secure, but I want it to be as secure as possible without affecting user experience).

I'm not taking into account what happens if a user reverses my Desktop App or gets access to my cloud hosting account because if this happens then the user will simply remove the checks or will know the shared secret.

Thanks in advance.

1 Answers1

2

Could I query your "Solution for 1st problem":

Solution for 1st problem: Both Desktop App and API share a Secret Key that the API will use to generate the JWT and the Desktop App will use to verify this JWT.

The way you're implemented this now - if somebody recovers your secret from the desktop app, they could use this to create a new JWT token that both the desktop app and the server would accept as valid.

JWT's provide a solution to this, you can use one of the asymmetric encryption algorithms to sign the JWT when you create it on the server (for example the RS512 algorithm).

This is preferable to using a secret shared by both the desktop and server applications, instead the desktop app just needs the public key of the key pair the server used to sign the JWT.

Cheers, Pete

GreatSeaSpider
  • 2,054
  • 16
  • 14
  • 1
    Hello!. First of all: thank you!. I've been avoiding RSA because I'm having trouble implementing it on the Desktop App, the WinApi used (cng) is not well documented and there is lack of information / tutorials. I will use HS256 for now and will change to RSA once I can make it work. Thank you! – roberto carlos Oct 22 '19 at 18:05