Prevent REST API to be called with forged payload [duplicate] - javascript

This question already has answers here:
Preventing cheating for on-line arcade high score board
(5 answers)
Closed 23 hours ago.
This is a security problem that I'm trying to deal with. I'm having a Nodejs REST Api and React frontend. The user logs in and server issues a JWT token which is stored in localstorage.
Now there is a game which user plays and as the game finishes the high score is recorded in database with POST api by passing high score in body of the request.
Later my application uses these high scores to award prizes to user so there is a monetary thing involved.
Suppose the user is malicious, he came to know about my POST api structure, he got token from local storage he knows how I'm sending high score in payload.He went to postman and hit the api, as I'm using CORS he gets an error. Now he comes to browser and opens console on my website and from there he calls the API and everything worked. He is now holding the high score and winning the prizes unethically.
Any suggestions what's wrong with this particular implementation or how it can be resolved. Thanks.

Short answer: Not possible. If you want the high score determination to be tamper-proof you must carry it out on the server, not on the client. See also When doing a booking system, where would it be better to do? Back end or front end.
Longer answer: You have not told us how the game itself is implemented. Does it leave any traces on the server other than the score? Because if you only want to store the score on the server, how could an honest player ever prove to the server that they earned the score by playing by the rules? The answer to this clearly depends on what the game is all about. Without knowing the rules of the game, I cannot imagine a better answer.

Related

How should i transfer live x and y positions in a MMO like browser game?

my difinition of "MMO" might be a little optimistic (maybe), but i have in mind to create my own online game where other players current (live) position is really important.
From my current reseach i have read that using a database for this matter will draw alot of power from the database and is quite insufficient to this live.
The game will not require to save and location after you logout.
The amount of players needed to be loaded at same time would be 50 players tops, since players will be grouped into diffrent servers / lobby.
So my questions is: How should i most efficient transfer live posistions of other players to other players in a online mulitiplayer browser game?
You should read about "Web Sockets". It is kind of connection that once opened between server side and client side app is does not end. Every moment client can send something, and server can send something without a handshake.
I no pro in web sockets but you will find many free articles and .pdf's on this topic.
If you want to send it to other users think of it like a chat with global room ;)
It's the best what comes to my mind as an example. One user sends a message to server (but in your case repeatedlivly like every 0.5s) and every logged user get's this data to his own browser.

Real-time user notifications from backend with PubNub, scalability, and over 9000 chat rooms

I'm working on a pretty fun web app project that can become rather big, and I have a chance to play around with this handy thing called PubNub as main real-time engine of application.
So it's a web application with Node.js backend, involves potentially huge amount of chat rooms between users and realtime notifications sent to users by backend when some data in DB is updated.
Usually, developing with Sockets.io, I will just subscribe each user to channel of his unique DB id, and also to chanels representing different chat rooms.
This way I can handle chat rooms and authentication on backend and after storing some personal notification in DB I can easily push them to channel named by user id, so if user is online - he gets it, if not - fine, he will see it on next login, notification is already in DB. And theoretically this monstrocity should scale just fine horizontally with help of redis pub/sub.
Thing that worries me about PubNub in this case is scalability. As I obviously have no insight on what is going on in PubNub backend's dark corners, I want to make sure that app is built in the way that it will be prepared to handle some obscure enormously huge amount of simultaneous users.
My question is, what is the best approach to building such a system with PubNub?
Am I correct assuming that it will be better, in need of pushing notification to specific user, to subscribe to this user's pubnub, push note and unsubscribe. As if I will keep all online-user channels open - then there is no point in PubNub instead of websockets on my server, as server will be anyway under load of all of those opened online-user channels and should be scaled just to maintain huge quantity of them.
What about user authorisation? Without involving my backend how can I be sure that user posting some message will not be able to fake his personality and will have exatly the same as he have authenticated inside application?
And generally (and via PubNub) what is the best practice to tackle huge amounts of chats per users? As say during application life each user may accumulate some decent amount of garbage chat rooms that have some users in it, though havn't been touched by anyone for a long time, and users just way too lazy to leave it manually?
Thanks for Your patience in reading this wall of text!
UPDATED Dec 5, 2021
If you are implementing a chat app, please refer to the PubNub Chat use-case documentation for full details. It has new features and UI components that are built upon the PubNub Platform.
UPDATED May 15, 2020
We have some new docs that will explain much of the below in much clearer terms.
And new features that can be applied to many of the questions/answers below:
Message Actions
Message Counts
Batch History (multi-channel message fetch)
Objects (Users, Channels and Memberships Metadata)
NOTE: I've sprinkled some of the above links down in the answers below.
First, let's address this...
Thing that worries me about PubNub, in this case, is scalability. As I
obviously have no insight on what is going on in PubNub backend's dark
corners, I want to make sure that the app is built in a way that it will
be prepared to handle some obscure enormously huge amount of
simultaneous users.
and this...
then there is no point in PubNub instead of WebSockets on my server,
as the server will be anyway under the load of all of those opened online-user
channels and should be scaled just to maintain the huge quantity of them
This is sort of backward because you would use a service like PubNub to ensure that your application scales to handle millions of users. PubNub has thousands of customers that scale to millions of users and 100's of billions of messages. Not knowing how PubNub does this frees you to implement the biz logic of your application.
But I think I get what you are saying. You are under the impression that your server has to be involved in each and every chat room interaction for every user, but that is only partially true. Mostly, your server will be used for authentication, some subscription maintenance (optional), and probably for sending messages out to one, many, or all end users, as required (depends on your requirements).
Here are some attempts to answer your questions although they are kind of a bit all over the place so I will do my best to answer what I think it is you are asking.
Question 1
This question seems to be directed at maintaining lots of subscriptions to channels and the scalability of that.
Generally speaking, every end-user initializes PubNub and subscribes to channels they need to listen to and publish to channels they need to send messages on. Typically, the channels (chat rooms in your case, I assume) they are publishing on are the same channels they are subscribing to, but they are different kinds of use cases. And you can subscribe to thousands of channels at a time (up to 20K per client). If you did this with WebSockets, how would you go about scaling this to millions of users? You would implement and operate (to scale) something similar to PubNub (not easy and not cheap).
Now, if a user is subscribed to a bunch of chat room channels but some or many are stale (user hasn't viewed or posted to in a while), you could have some code on your server (or the client) that monitors the activity of users and unsubscribes them from those stale channels. This is possible using channels groups. Each end-user would have their own channel group that contains all the channels they are listening to. And the client code or the server code and add and remove channels to/from those end users' channel groups.
Question 2
UPDATED DOCS: https://www.pubnub.com/docs/platform/security/access-control
Now this question is a bit more clear and focused and is asking about authentication (login) and how to ensure someone is who they say they are and how to handle authorization (what they can and cannot do) and where/who controls this.
The answer is, you control the authentication (login) to prove that the person is what they say they are. Your log-in process checks for a valid username/password and in the user record, you will have a list of access controls for that user. With that, you generate an auth-key that you grant read and/or write access to one or more channels. This grant is a PubNub operation that your server invokes. The auth-key is passed back to the client and the client code initializes PubNub instance using the pub/sub keys and this auth-key that PubNub servers use to check for access based on the channel and the operation being requested (subscribe to this channel, publish to that channel, etc). If the auth-key does not have the proper access, the PubNub server will deny access (403 response).
There's more to all of this but this is a good start. Read up on PubNub Access Manager for the SDK you will be using on our docs page. For example, you can start with the JavaScript SDK Access Manager docs and tutorials.
Question 3
UPDATED DOCS: https://www.pubnub.com/docs/platform/channels/receive#subscribe-to-channels
I believe I answered this sufficiently with question 1 - Channel Groups. Start with the JavaScript SDK Stream Controller (which provides Channel Group feature) docs and tutorials.
I hope I have managed to move you a few steps further along your journey to a highly successful real-time, data stream application using PubNub. Please reply with any additional questions you may still have.
*Answers to your new comments:*
Thanks for your follow-up comments. It is very clear what you are asking now.
I will need to compare chat room timestamp with personal user last-read timestamp for this, so it seems that I need to listen to those channels from back-end and update user's last-reads, or to trust into the front-end, and get timestamps from a user directly
No, you do not have to listen to the channels on your server. Yes, from the client app, you will keep the timestamp of the last received message. When the user comes back online, you use this timestamp to get history for the channels the client was subscribed to. Many have done this successfully and we are going to be releasing some amazing features in the coming months that will simplify this considerably.
pushing real-time notifications to users from the back-end. Do I need to be subscribed to all of my user channels if I want to push notes to them at any time?
You can publish on any channel without actually subscribing to it first. So your server can publish to channels as it needs to.
And as before, keep coming with more questions as you require.
*Great follow-up questions again. Here's what I suggest*
... it makes sense to not request all of those chat rooms from DB and join via pubnub all of them, but rather implement pagination... how user can be aware of new messages that may appear in his old chat rooms?
Again, you can stay subscribed to 20K channels using channel groups. You can subscribe to 10 channel groups with 2K channels per channel group - but I'd recommend just limiting the user to 100 or less because that seems like a sufficient limit to impose in your app. But pick whatever upper limit you want and when the user hits that limit, force them to leave another chat room first or suggest they leave one of the top 10 most inactive, or some algorithm that makes sense for your app.
UPDATED DOCS: https://www.pubnub.com/docs/platform/channels/receive#subscribe-to-channels
Getting the # of missed messages does require a full history fetch, but we are going to be providing improved APIs to make this simpler in the near future. But if the user is registered for push notifications on all these channels, the device would be able to receive these push messages and your app can keep that count locally. We will have a "how to update the badge count in background" article being published soon. You could also use that to keep track of the number of missed messages per channel (chat room).
For now I just want to limit the number of rooms available for users to let's say a hundred and request and join them without pagination.
UPDATED DOCS: https://www.pubnub.com/docs/platform/channels/retrieve
We do have customers that do this without worrying about pagination. They just retrieve history on the 100 channels the device is subscribed to. With the background badge count updater strategy, you will have the advantage to know which channels to fetch from when the app becomes active. I will post the link to that article here once it is published.

Facebook signed_request data and some security concearns

We've just developed a small Facebook puzzle that people win some gifts from our customer. I'd like to ask a few questions since I'm pretty stuck despite tried lots of things. First I'd like to write what we have and then will explain our problems.
What we did so far:
Root of application (/) checks for signed_request in POST params, extracts information from it to see if we've registered the logged in user into our database. This checks are also used to understand if the request is sent from Facebook or not to prevent requests coming outside of Facebook. (will write why we want this)
Once the application is successfully rendered, Facebook JS API takes place, does its checks and sets the fbsr cookie. We use that cookie information while processing ajax requests to check if the request really belongs to the logged in user (e.g.: scores being sent for a user belong to the logged in user).
We implemented CSRF protection and another protection to check if the requests are POST and more specifically AJAX requests and return 40x if not.
Problems:
Despite I do some checks to prevent spoofed scores, I couldn't think of a way that the logged in user could improve its own scores by simply calling the same JS code I do for real scores. We just ignored this for some time until we just found out that some people seem to take advantage of this bug.
One way I thought of is to ignore all requests except coming from Facebook. Since the ajax requests are blocked (cross site) we should have been safe. However this leaded to another problem that, once we redirect users to e.g. leaderboard the signed_request data is lost and our index page returns 40x once the user tries to go back since our application thinks that the user tries to visit our application outside of Facebook.
I hope that I made our problem clear. Gaming time is calculated by Flash (game is programmed in AS3) and it's sent via JavaScript methods to server side. We could have done it in Flash but that only prevents our problem from becoming trivial. Afterall we'd have the same problem if we had implemented the game in HTML5.
Any thoughts, suggestions are really welcome and thanks for your feedback!
This is a bug by design. You are calculating the scores on client side and then send them to the server. The server has no way to validate if the score is correct. This can ALWAYS be faked by clever users.
Never ever ever calculate things that could give users advantage on clientside. Clientside is evil. Everything on clientside can be manipulated - no matter how hard you try.
Calculate your scores on the server and use the client side only to display them. Every other solution is crackable.

Getting all Users' scores using the Facebook Score API

Using the Scores section of the Facebook Graph API, is there a way to request the scores of all users? Additionally, can they be requested sorted, ascending or descending?
Short Answer: No.
Long Answer: Under the Graph API, the User retains all Application data specific to their user account. This may be for privacy reasons (to enable a user to confidently delete all of their application data at will, perhaps) or simply because Facebook has found that this relationship model is more efficient. Whatever the reason, queries on the Application object can not be made to "get all Users". Another way to look at it would be User--has-many-->Application and not Application--has-many-->User.
The workaround we are using involves querying for User-->Friends, caching the returned list of friend ID's, and then firing off individual User-->Application Score at each friend. The upside is that it works, while the downsides are that it takes more time, wastes effort querying friends who either don't play our game or don't share their game data, and causes some of our users to bump up against Facebook's 600-in-600 queries-per-second limit.

Why can't post scores via Scores API in Javascript?

I'm writing a javascript game library that I want to integrate with Facebook Scores. Games made with my library typically run on static file servers (i.e. just ordinary HTML+JS, no server side scripts).
I've been looking at the scores documentation and have come across this problem: you can only submit a score with an app access token.
Why?
Correct me if I'm wrong, but it seems I can't get an app access token unless I have the app secret, and it seems obvious I should not put the app secret in javascript. For most of these games, server side scripting is out of the question. So I have no way to get an app access token, so none of these games can submit scores.
What seems especially dumb is if the user grants the app the "publish_stream" permission, you can automatically make a wall post along the lines of "I just scored 77777 in MySuperGame!". You can do that with just pure HTML+JS. But you can't post a score.
Am I missing something or is the API just a bit dumb about this?
Because the client can send any information it wants to the server, it is a good idea not to trust it. Since scores are usually a way to objectively determine the skill of a player, letting the player determine his own score would directly undermine the function of scores. So the score is determined by an independent party; the server.
If Facebook did not require an access_token, it would be very difficult for other games to secure the scores. You could ask the Facebook SDK developers to add an insecure alternative to the Facebook SDK, but adapting your games to use the secure method is probably easier.
I would recommend creating a system where choices made by players are sent to the server, where they are checked, and where the score is calculated and sent to Facebook. For a simple quiz these choices are simply the chosen answers, in a complex 3d Game they might include all movement and interaction with the world.
If extensive server scripting is really out of the question, you could reduce it to one script on the server that relays the score sent by the client to Facebook.
If you could do it from javascript then anyone could forge their scores by just running a few commands via console.
I'm not sure if that is the reason we don't support it but it seems like a likely one.

Categories

Resources