0

I have an API and an SPA. The SPA is all anonymous but I want to ensure the caller of the API is authorized to do so.

It seems that all of the OAuth best practices, e.g. PKCE, depend on a user actually logging in, which will never happen.

Am I overthinking this?

Both apps are hosted in Azure and I've gone down the path of setting up API Management there but that doesn't seem to be a good fit for this scenario. The API is a .net core Web API so if there are solutions I can implement on the API side I'm open to those as well.

  • 1
    What do you mean by the caller is authorized to do so if they are not logging in? How do you know their identity? – Limit May 09 '20 at 02:09
  • The caller is the SPA, I'm trying to figure out the best way for the API to verify that the requests come from consumers that we authorize. In my server based apps I'd use client credentials flow but that doesn't seem appropriate for this. – Chris Rockwell May 09 '20 at 02:24
  • Why do you think the credentials flow is not appropriate? – Limit May 09 '20 at 02:28
  • Primarily based on reading I've been doing over past couple days and those seem to call out that it's not ideal because both the client I'd and secret are readily available. If you cant tell yet, this is my first time thinking about this in the context of an SPA used by anonymous users only. – Chris Rockwell May 09 '20 at 02:32
  • So just to be clear, you don't particularly care who calls the POST API as long as they use the correct client (the SPA). So you just want to verify the client that is making the connection to your API – Limit May 09 '20 at 02:35
  • That's right. For more context, we send links to known users, those links uniquely identify a user but we dont want to slow them down with requiring a login. They are on an honor system to not pass those links on to "smarter" people (its spaced repetition learning) – Chris Rockwell May 09 '20 at 02:41

1 Answers1

3

The general best practices are to use SSO/client auth. But since they don't apply to you, you can consider this approach:

If you trust your users to not share the unique links that you passed sent to them, you can use that unique property of those links to request a session variable from the server and then pass that session variable in all the requests that you make.

This request to fetch the session variable can be made at the page load time or at any point before the first POST call to the server. This will increase the time before your users can make a POST call to the server but will at least ensure that the POST call is made by a legitimate user and through your SPA.

Of course, whatever requests you make to a server can be mocked by replaying the request. There is no way to circumvent that.

Limit
  • 3,191
  • 1
  • 16
  • 35
  • Thanks. So in this situation the primary risk would be a user shares the link and someone uses that link to enable the API usage via another application? But because that link is unique to this users interaction with the app (new link for each question) someone trying to use the API unapproved would need access to a new unique link every time. (Once a question is answered for the first/final time, the API would reject requests do update the answer anyway). Does that seem accurate? (1/2 wondering if this use case really doesn't warrant thinking a whole lot about API authorization) – Chris Rockwell May 09 '20 at 14:59
  • Yes. If you are avoiding replay attacks by rejecting a second use of the link, you should not worry about user sharing the link *after* using it. Whether it warrants a whole lot of thinking about API authorization depends on how much do you care about the user using your client to use the API vs using cURL/Postman – Limit May 09 '20 at 17:14