After reading around it appears that trying to protect a publically accessible API (API used by an app/site that does not need a user to log in) appears to be fruitless, e.g. store key in app, user can reverse engineer app.
My question relates to how one can protect as much as possible and slow down abuse of a public accessible API...
Rate-limiting? Check request origin (although can be spoofed).... anything else?
Also if the site is SSR, could it just be protected by the server's IP?
YOUR QUESTIONS?
After reading around it appears that trying to protect a publically accessible API (API used by an app/site that does not need a user to log in) appears to be fruitless, e.g. store key in app, user can reverse engineer app.
Security is all about defense in depth, thus is all about adding as many layers as you can afford and required by law in order to mitigate the risk, therefore any defense you add it's one more layer that will prevent that simple/dumb automated scripts from accessing it, while at same time will increase the level of skills and effort necessary for an hacker poking around to overcome all defenses.
Rate-limiting?
This is kind of mandatory for any API to employ, otherwise an automated script can easily extract an huge amount of data in seconds. The more strict this rate limit is applied, the greater may be the chances for other layers of defense to detect that unauthorized access to the API may be happening and try to mitigate/block it. To bear in mind that the rate limits can be bypassed by adapting the attack to make requests that do not trigger it, and in some cases easily automated for that Software that give back in the response header the throttling values being applied.
Check request origin (although can be spoofed)....
Yest it is easily bypassed, but why not? It will be one more layer of defense that filters out some dumb automated scripts/bots.
Also if the site is SSR, could it just be protected by the server's IP?
No matter if a SSR site or any other type of app, when used from a mobile phone the IP address can change during the load of a page or mobile app screen, because when the phone switches between masters the IP will change. Also to bear in mind that in an office or public wifi all the users on it will have the same IP.
The use of it as a blocking measure on its own needs to be carefully evaluated, and normally requires fingerprinting the request in order to reduce the risk of blocking other valid users sharing the same network.
I would use it very carefully to avoid/block/throttle requests only when I could establish that hey are known bad IPs, that you can collect from your own requests history and/or from public datasets.
WHO IS IN THE REQUEST VS WHAT IS MAKING THE REQUEST
A common misconception around developers of any seniority is about not being aware that the who is in the request is not the same as what is making the request, therefore we will first clear it out...
The Difference Between WHO and WHAT is Accessing the API Server
While your API is not using user authentication is important to be aware of this distinction in order to better perform informed decisions around the security measures to be adapted in the API server.
I wrote a series of articles about API and Mobile security, and in the article Why Does Your Mobile App Need An Api Key? you can read in more detail the difference between who and what is accessing your API server, but I will quote here the main takes from it:
The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?
The who is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.
The best way to remember the difference is to think about the who as the user your API server will be able to Authenticate and Authorize access to the data, and think about the what as the software making that request in behalf of the user.
DEFENDING THE API SERVER
My question relates to how one can protect as much as possible and slow down abuse of a public accessible API...
For Mobile APIs
For an API serving only mobile apps you can use the Mobile App Attestation concept as I describe in my answer to the question How to secure an API REST for mobile app?.
For Web APPs
For an API that only serves a Web app I would recommend you to read my answer to the question secure api data from calls out of the app?.
DO YOU WANT TO GO THE EXTRA MILE?
anything else?
It seems you already have done some research but you may not know yet the OWASP guides and top risks.
For Web Apps
The Web Security Testing Guide:
The OWASP Web Security Testing Guide includes a "best practice" penetration testing framework which users can implement in their own organizations and a "low level" penetration testing guide that describes techniques for testing most common web application and web service security issues.
For Mobile Apps
OWASP Mobile Security Project - Top 10 risks
The OWASP Mobile Security Project is a centralized resource intended to give developers and security teams the resources they need to build and maintain secure mobile applications. Through the project, our goal is to classify mobile security risks and provide developmental controls to reduce their impact or likelihood of exploitation.
OWASP - Mobile Security Testing Guide:
The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.
For APIS
OWASP API Security Top 10
The OWASP API Security Project seeks to provide value to software developers and security assessors by underscoring the potential risks in insecure APIs, and illustrating how these risks may be mitigated. In order to facilitate this goal, the OWASP API Security Project will create and maintain a Top 10 API Security Risks document, as well as a documentation portal for best practices when creating or assessing APIs.
Just for a quick answer
I can suggest at least one via solution which is to use an API Gateway (like Kong, Express Gateway or AWS API Gateway, etc.).
The API Gateway allows you to create API consumers (e.g: buyer mobile app, seller mobile app, buyer TV app). For each API consumer, an auth key (or even OAuth 2.0 credentials) will be generated and asigned respectively.
You then can use the auth key or OAuth 2.0 credentials (ID and secret) to access the APIs securely (even for the public ones, as API Gateways will only allow access from valid API consumers).
How about request from web?
You can configure API Gateway to detect requests from web and instead of using auth key or Oauth mechanism, it can use domain white-listing CORS protection mechanism.
How about user access token (generated from successful login)? Any conflict here?
IMHO (emphasized), after getting user access token (e.g: a JWT), for every authenticated-user-only requests you will send both API Gateway auth key token user auth access token. Referencing to Exadra's answer above, we can consider API Gateway key is to verify the "what" (mobile app) while user access token is to verify the "who" (login user).
Related
I am trying to be sure that I understand it correctly:
Is OAuth a bridge for only third party authenticator those so common like Facebook, Google? And using it improves user experience in secure way but not adding extra secure layer to Django login framework? Or only Authorization Code grant type is like that? Can I take it like this?
What is OAuth?
According to RFC 6749:
The OAuth 2.0 authorization framework enables a third-party
application to obtain limited access to an HTTP service, either on
behalf of a resource owner by orchestrating an approval interaction
between the resource owner and the HTTP service, or by allowing the
third-party application to obtain access on its own behalf.
Essentially, it is an authorization protocol used to share permissions between multiple applications.
If you decide to implement OAuth, your application will be the one to allow other services to programmatically view your users' data and act on their behalf, if needed.
Whenever an application requires access to another service that you use, it probably uses OAuth to perform those actions. (e.g. When games used to ask us to allow posting on Facebook on our behalf.)
What OAuth is not?
By looking at your question, I feel like there's a misunderstanding of OAuth.
OAuth is not a bridge for third-party authentication methods. If you are looking for this type of authentication mechanism, you should take a look into Single Sign-On (SSO). For Django, you can use django-simple-sso.
Does it enhance security?
Depending on the use case, yes, it can enhance security.
If your application needs to exchange information with other services, it is a good practice to limit what these third-party services are able to do in your app, feature and time-wise.
Let's say, for example, that your user needs to give permission to another application to gather information from yours:
If you were to use the old-fashioned e-mail and password combination method, these credentials would be exposed in case of this third-party service had a data breach.
Using OAuth on the other hand is much more secure, as the credentials stored in the server would not contain the user's password and have very specific roles, apart from being easily revoked.
If you have a Django app I would say that you don't have to implement OAuth - you should be fine with any login functionality Django offers.
OAuth is commonly used when different services talk to each other. These don't have to be third-party services, they can belong to the same party. For example, when you have a Single Page Application or a Mobile App that want to call your backend API to get some data. Then it's better to use OAuth as it is a standard and it helps you to implement authorization in a secure way.
When you think about "login with Google/Facebook", what you actually want is an SSO solution (Single Sign-On). That solution is very often implemented with OpenID Connect (OIDC), which is a protocol built on top of OAuth. Still, you can use just OIDC to log a user in with Google, get an ID Token, and then be able to authenticate the user to your Django app based on the ID Token from Google. You don't need OAuth for that (in the sense, that you don't need to get access tokens from Google, you don't need your own Authorization Server, and you can rely on cookie-based sessions).
What is the best way to do user management in a single page JS (Mithril) app? I want users to login to load preferences and take on a role so they gain certain permissions. I have a REST API backend written in Python (Falcon web framework). Having read a bit into it, it seems to boil down to sending credentials to the backend and get a token back. But the question is how that should be done. It seems that tokens are a better method than cookies, but that has effects on the exchange of secrets/tokens. the 'xhr.withCredentials' method seems to be cookie based for instance. JWT (json web tokens) seems like a modern, interesting option, but it's hard to find a clear explanation how it could be used with a SPA.. And once the Mithril app has a token, where should I store it and how should I use it with subsequent requests?
This isn't so much about Mithril, actually the only Mithril-related area is the server communication. That is done with the m.request method (docs here), but you need to create an object for all server communication that requires authentication.
That object should have knowledge about the auth system and detect if a token expired, then request a new one, take proper action if things fail, etc. It's a bit of work, but the process is different for most auth systems, so there's not much to do about it, except using something that already exists.
Being a small and lean MVC framework, Mithril doesn't have any security-related features built-in, but the m.request method is very powerful and you should use that inside the auth communication object.
The client-side storage will be in cookies or HTML5 storage. Here's an StackExchange answer that goes into more depth: https://security.stackexchange.com/a/80767 but the point is that this isn't Mithril-related either.
Thanks for linking to the tokens vs. cookies article, it was very nice!
I would like to write a simple desktop application for personal use that uses the Spotify Web API to build playlists.
As far as I can tell, however, there's no way to use the API without providing a callback URI, which I don't have, seeing as I don't have a domain or server of any kind (other than my personal computer).
Is there a way to use the API without a URI?
If not, what is the best way to set up a callback URI? I don't have much of any experience working with web applications or client / server stuff, and the APIs I've used in the past haven't required any kind of callback.
Some background first, this answer became a bit longer than what I anticipated.
You need an access token. There are three ways to retrieve an access token; Authentication Code flow, Client Credentials flow, and Implicit Grant flow. These are all part of the oAuth 2.0 specification, each with its own purpose.
Since you're going to modify a user's account, you need that user's permission. Now, if you didn't do any actions that required user permissions, you could've used the Client Credentials flow. That's probably the easiest flow to learn since it just requires a request from your server to Spotify's server, and the response contains an access token. No callback/redirect URI is necessary.
As I'm sure you've read, the Authentication Code flow and Implicit Grant flow both require a callback URI. This is because a flow that includes a user, and the callback URI is where Spotify redirects the user after they have entered their password on Spotify's site.
The Authentication Code flow and Implicit Grant flow has benefits and drawbacks. Access tokens retrieved through the Authentication Code flow can be refreshed, but both return tokens that are valid for one hour. This means that a user that's authenticating using the Implicit Grant flow must reauthenticate after an hour. However, the Authentication Code flow does require some backend work, since it needs to make a request to exchange a code given from Spotify's server for an access token. The Implicit Grant flow is more straight forward - you get the access token and off you go.
The callback URI can be a localhost address, so if your desktop application would spin up a web server locally you could handle the callback on the same machine that the application is running on. (It's probably a good idea to not run the web server on port 80 since that might be used by something else.)
There's skeleton code for each of this authentication flows available on Github, see web-api-auth-examples. Read more about the flows in our Authorization Guide. If you choose to run a web server on the user's machine, I recommend that you use the Implicit Grant flow since that doesn't include any server-to-server requests, so you won't have to expose your client_secret exposed in the code. (As opposed to the Authorization Code flow.)
Also, since you're coding in Python, I recommend that you have a look at spotipy, a wrapper around the Web API packed with convenient methods that'll save you some time. If you do go ahead with the Implicit Grant flow, you should have a look at spotify-web-api-js, which has a similar purpose. Note that these wrappers are not at all required to work with the Web API but they'll make your life easier.
I would like build a REST API using the Django REST framework. Initially its client would be a web application, but conceivably future clients could include mobile applications.
Unfortunately I'm finding the list of authentication classes listed in the documentation a little confusing. It looks like TokenAuthentication would meet my needs. I would rather avoid the cognitive overhead of OAuth unless there is a compelling security reason to go that way.
This is a decision I want to get right at this very early stage. Can anyone provide any advice?
Edit: Although hopefully not relevant, I thought I'd mention I'll be using Neo4j as a back-end for the application, not a conventional SQL database.
Django REST Framework gives you the flexibility of having multiple authentication methods. Since I've got some time, and it will be useful to future visitors who have similar questions, I'll outline the benefits of the most common authentication methods.
Initially its client would be a web application, but conceivably future clients could include mobile applications.
Typically when working with web applications that are on the same domain and Django instance as the API, most people use SessionAuthentication as it interacts with the server using the existing authentication methods. Authentication works seamlessly, so you don't need to go through the second authentication step.
Most APIs also support some form of BasicAuthentication, most likely because it is the easiest to test with but also because it is the easiest to implement. For your web application, this isn't the recommended authentication method, but for your mobile application it's not uncommon to see it being used. I personally would recommend a token-based authentication, so you don't have to worry about clients intercepting user's credentials.
It looks like TokenAuthentication would meet my needs.
Many people use TokenAuthentication because it is relatively simple to understand and use, and it seems to meet everyone's needs at first. Tokens are directly attached to users, and they do not automatically rotate (though you can make them automatically rotate), so every client working on behalf of the user gets the same token. This can be an issue if you ever need to revoke the token, as all other clients will have their token invalidated as well.
I would rather avoid the cognitive overhead of OAuth unless there is a compelling security reason to go that way.
OAuth 2 (OAuth2Authentication) gives you token rotation and token expiration on top of the benefits of TokenAuthentication. There's also the benefit of being able to revoke individual tokens without affecting other clients who are authenticating for the user. You can also limit clients to individual areas of your API through the use of scopes, which is useful if you have certain areas of the API that are more often used than others.
I'm also going to mention JSON Web Tokens, because while I haven't used it, it's been showing up quite a bit in the support channels. It works very similar to TokenAuthentication as far as retrieving tokens, but it has the added benefit of unique tokens for clients and token expiration.
I have an application that has a "private" REST API; I use RESTful URLs when making Ajax calls from my own webpages. However, this is unsecure, and anyone could make those same calls if they knew the URL patterns.
What's the best (or standard) way to secure these calls? Is it worth looking at something like OAuth now if I intend to release an API in the future, or am I mixing two separate strategies together?
I am using Google App Engine for Python and Tipfy.
Definitely take a look at OAuth
It is quickly becoming the "de-facto" standard for securing REST APIs and a lot of big companies are using it, including Google, Twitter and Facebook just to name a few.
For Python on GAE you have two options:
The most straightforward way (IMHO) is using David Larlet's library for OAuth Support in Django available on BitBucket.
But since you're not using Django, maybe you want to take a look at the python-oauth2 library that's available on GitHub, and is considered the most up-to-date and unit-tested implementation of OAuth for Python 2.4+.
Either way I think you'd be much better using OAuth than rolling your own service security solution.
Securing a javascript client is nearly impossible; at the server, you have no fool-proof way to differentiate between a human using a web browser and a well-crafted script.
SSL encrypts data over the wire but decrypts at the edges, so that's no help. It prevents man-in-the-middle attacks, but does nothing to verify the legitimacy of the original client.
OAuth is good for securing requests between two servers, but for a Javascript client, it doesn't really help: anyone reading your javascript code can find your consumer key/secret, and then they can forge signed requests.
Some things you can do to mitigate API scraping:
Generate short-lived session cookies when someone visits your website. Require a valid session cookie to invoke the REST API.
Generate short-lived request tokens and include them in your website HTML; require a valid request token inside each API request.
Require users of your website to log in (Google Accounts / OpenID); check auth cookie before handling API requests.
Rate-limit API requests. If you see too many requests from one client in a short time frame, block them.
OAuth would be overkill in your current scenario (potentially insecure), in that it's designed to authorize a third party service to have access to resources on behave of the user.
Securing AJAX request via an authorized user
AFAICT, you are in control of the client, resources and authentication; so you only need to secure access to the URL's and possibly the communication between client and server via SSL [2].
So, use Tipfy's auth extension to secure your URLs:
from tipfy import RequestHandler, Response
from tipfy.ext.auth import AppEngineAuthMixin, user_required
class MyHandler(RequestHandler, AppEngineAuthMixin):
#user_required
def get(self, **kwargs):
return Response('Only logged in users can see this page.')
Securing AJAX request without an authorized user
If a user is unknown, then one could apply CSRF preventions to help protect the REST service from being called from an "unauthorized" client. Tipfy has this built-in to it's WTForms extension, but it's not AJAX. Instead, the session extension could be used to apply an "authenticity_token" to all calls, that needs to be verified on the server.