0

I've created a website for a tennis league. The two main pages are standings and schedule. When a user accesses the site, I'd like to have them select the league and season first. For example, the site could host standings/schedules for multiple leagues. So the user could select league ABC and season Fall 2016.

For each Web API request after the user selects league and season, I'd like the Web API to remember this selection for the user. I could store the values when the user first selects them:

HttpContext.Current.Session["League"] = league;

Then, in subsequent calls, the Web API knows the league to use when getting the standings.

This can be bad for two reasons:

  1. The Web API is no longer stateless, and the call from the browser would have to hit that specific Web API server on future calls.

  2. If the Web API server is rebooted, we lose that data and would have to deal with it on the client/web side.

I could forget all that and store the league in session on the browser, then pass that info to the Web API. However, we shouldn't be trusting info from the browser. What's to stop someone from using dev tools in the browser and entering any league they like?

Another option would be to store the league selection in the DB for the user, but then I'm making extra DB calls for each request to retrieve this info.

I know I'm missing something, as this has to be a common issue that's been solved. What's the right way to remember the league for a user after they originally select it? The server side needs the league so it can get the correct standings/schedule for it on subsequent calls.

3

I would keep the API stateless and I wouldn't assume that it is always consumed by "users" per se. Any other process could be consuming the API. You can, however, know the identity of every consumer and maintain authorization related to that identity.

So when a call is made to get a league and season, why not have another endpoint that gets standings given a league and season reference of some kind (name, Id, whatever)?

You mention that this could be exploited by someone passing leagues and seasons other than what they originally selected. But that's not a problem if you are maintaining authorization over the leagues, seasons, and standings given the caller's identity. So if a user changes the request to something they don't have authorization to, return a 403 Forbidden.

  • Thanks, Mark. That's a good point about other processes hitting the Web API. As far as checking for authorization on each request, that's what I was trying to avoid. My thought process was to check the first time, then store that info so subsequent requests could assume the correct league and season when getting standings. – Bob Horn Jun 4 '17 at 0:57
  • @BobHorn You can cache the result of the security check on the server (or cache the info used to determine the result, if it's common for several security checks). Refreshing the cache because of a (rare) app server restart is a non-issue. – gregmac Jun 4 '17 at 1:41
  • After thinking about this further, you're right, Mark. Adding state to the REST API goes against the point of a REST API. I think the right thing to do is cache in the browser, then validate through authorization on each request. – Bob Horn Jun 4 '17 at 1:43
  • If the security check to ensure the user has access to specific data is time consuming, one approach you can use is to provide the client a "capability", that is an unforgeable reference that allowed them to bypass the security checks when they use it. This could be a string that contains the object id that access is granted to and a secure hash of that id with a secret key that is only known by your api servers. You can also time limit the reference by including a timestamp. The advantage of this over cacheing the check is that the capability can be checked by any server in your cluster. – Jules Jun 4 '17 at 14:33
  • I would just like to second that a stateless backend is indeed the best approach. Regarding checking authorization, if the data from a GET request is not sensitive it makes sense to simply expose it with no authorization. The requests that does stuff (POST, PATCH, PUT) will often require authorization and here it is important to validate all parameters that the user indeed has the right to do what he requested. – Esben Skov Pedersen Jun 4 '17 at 17:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.