DEV Community

Discussion on: Cryptographically protecting your SPA

Collapse
 
rstar2 profile image
Rumen Neshev • Edited

Read the article, comments and even the simple repo, and still don't understand the point of all this.

First, not related to the security problem but to the implementation of this "fix" - So you basically did some form of JWT, why didn't you just use JWT protocol in the first place, like you said already have for authorizartion. Your server can send a signed JWT token (the payload of which can be whatever your server needs, it's not restricted to auth usecases only, like in this case JSON.stringify(responseData)). And your client can just decode/verify it. If the current user-hacker tries to change this JWT token or it's payload it will fail. This are 2 lines of code, one in server and one in client, using the right libs which apperantly you already use for the authentication part.

Second it's best to describe what your app is doing but what I figured it's smething like:

  • Bob as a employee logins and sees he has bonus of 20$ as this is what the server sends him.
  • Bob sees that server sends to John 40$ so he tempers his server's response and instead 20$ he now "has" 200$. Bob is happy seeing on his screen 200$.
  • But he figures out that Alice receives from the server "isAdmin: true" so Bob decides to temper his response to be "isAdmin:true" also and he enters the "protected" admin page and can now grant whatever bonus he whats to himself (or maybe his friends).

If this is the case and you (or your boses) think that you've "secured" it with what you've done then obviously no need anyone to convince you otherwise. If this is not the situation then just explain what at all you are trying to protect and then people will willingly be happy to provide guidance and help

Collapse
 
matpk profile image
Matheus Adorni Dardenne

I need to verify the signature on the client, and JWT verifies it on the server (at least, that is how I learned it). This doesn't help in this case, because the hacker can intercept any attempt to contact the server to validate the signature and fake the response saying it passed.

I came across the repository "jose js" recently and it seems there is something "like" what I did there, but I couldn't make the time to get to know it yet.

I can't disclose details about the application. But it is like a 360-evaluation tool, and people's final score is related to their bonus. If, by messing around, they find a way to modify their scores, this could impact their bonus.

The hackers reported this as a critical issue because of the profile of the potential attackers; employees with low tech skills and good incentives to mess around. Looking back, maybe I should have made it clearer on the article. I expected people to just "get it", but I guess I shouldn't. Lesson learned.

Many people have provided helpful guidance, and I gathered a lot of useful information to discuss with the team. We're fuzzing the API to battle test our validations, for example.

Collapse
 
rstar2 profile image
Rumen Neshev

The JWT's payload can be verified anywhere, successfully decoding it is actually the verification, if the payload is tempered then decoding/parsging it will fail. It is most likely what you already do with the auth JWT , you receive from server JWT with lets say payload claims like "user:xxx", "admin:false", "prop:value", so client verifies it by successfully decoding it and sees "Aha, the payload say user:xxx, prop:value, ..." and so on. If someone doesn't matter who, man-in-the-middle or same user tempres it and tries to put "user:yyy", "admin:true" then the decoding will just not be possible. Read it more properly on jwt.io/ , I'm not native english speaker.

Thread Thread
 
matpk profile image
Matheus Adorni Dardenne

Thanks, I'll read, but as I understand, the decoding of a JWT is simply parsing it's content as base64, it would still need the secret to validate it, so that's why it happens on the backend... perhaps I'm missing something, so I'll look into it. It is possible that JWT accomplishes what I needed, but we simply didn't know at the time.

Thank you very much.

Thread Thread
 
sgtwilko profile image
sgtwilko

There's two main types of JWT, and inside those there's a selection of cryptographic cyphers you can use.

You can sign a JWT with an RSA private key on your backend and verify it using a public key on your frontend, or any on any API endpoint.

This type is JWS, And as you mentioned, this version is just base64 encoded data, but with exactly the sort of cryptographic signature you're after.

The other type is a JWE, and in this form the entire payload is not only signed but encrypted, so you cannot see the payload in flight.

Again, this can be decoded and verified on both the front and backend.

Thread Thread
 
matpk profile image
Matheus Adorni Dardenne

Cool. JWS seems to work like what I did. Could've saved me some time, but I still enjoyed building this as I learned a lot.

JWE I suppose the front would need to have the secret, so it wouldn't really help. But I guess it can be good for server to server communication?

Thanks for the info.

Thread Thread
 
sgtwilko profile image
sgtwilko

Both JWS and JWE can work either with PSK or public private keys.

It depends on the crypto chosen.

Using RSA or Eliptic curve would work with public private keys, just as your solution did. With these the front end would only need the public key to (decode JWEs &) verify the JWT.

Nothing about JWTs is limited to backend, it's just as applicable to frontend.