9

I'm writing a web app with a separate frontend and backend. The frontend is written in React, and the backend is a node.js server running an Express endpoint. How do I ensure that only my frontend can access the API, and not anyone else? My API URL is exposed in my frontend client side code, so anyone can see that.

I added JWT authentication to my API, but I still need to have an unprotected /login endpoint in order to generate the JWT token, and in order to login to generate the token, I must post both a username and password from my frontend, which other users can see, since it's done from the client side.

What is the proper way of securing an API that is hosted on a separate backend like this, so that only my frontend can access it, in a way where nobody can see what credentials are being used to access the endpoint?

WhoopsBing
  • 493
  • 1
  • 6
  • 12
  • 4
    You can't. Your API is on the internet. Anyone can access it. You can require an account and login credentials for the account before allowing access to the API, but once someone has an account and credentials, they can access the API from their own script rather than via your web page. This is how the web works. Not much you can do about it. And credentials being used by the client cannot be hidden. All data that is EVER on the client can be looked at by a hacker on the client. This is the way of the web. – jfriend00 Nov 15 '17 at 02:05
  • 1
    Oh I see. That makes sense. How do companies generally deal with this problem? For example, with a site like Reddit, I'm sure it would be very easy for a hacker to make a million posts if they got the API credentials. How are the credentials generally stored? Right now they're literally just in my client side code. – WhoopsBing Nov 15 '17 at 02:24
  • Larger companies will typically monitor their API usage to look for inappropriate use. This includes rate limiting, detecting behaviors and sequences that are not typical of a regular user. When they detect inappropriate use, they will often ban the offending account, either temporarily or permanently. This is also why some pages use techniques to detect if an actual human is individually causing the operation such as reCaptcha. – jfriend00 Nov 15 '17 at 02:33
  • Ah I see. Those definitely seem like some good sanity measures for protecting an API. In terms of storing actual credentials to access the API from my frontend, do you think storing them in a JSON file and then loading that file into client side variables is fine? Or is there a way for people to easily see the contents of my client side files? – WhoopsBing Nov 15 '17 at 03:35
  • I don't know what you were thinking of for storing credentials locally, but if this is Javascript that runs in the browser (which I assume you meant by React front-end), then Javascript does not have access to the file system. You can use a cookie or local storage or a newer storage API like the IndexdDB API. – jfriend00 Nov 15 '17 at 04:40

1 Answers1

10

You can't. Your API is on the internet. Anyone can access it. You can require an account and login credentials for the account before allowing access to the API, but once someone has an account and credentials, they can access the API from their own script rather than via your web page. This is how the web works. Not much you can do about it. And credentials being used by the client cannot be hidden. All data that is EVER on the client can be looked at by a hacker on the client. This is the way of the web.

Larger companies will typically monitor their API usage to look for inappropriate use. This includes rate limiting, detecting behaviors and sequences that are not typical of a regular human user. When they detect inappropriate use, they will often disable that action or ban the offending account, either temporarily or permanently. This is also why some pages use techniques to detect if an actual human is individually causing the operation such as reCaptcha. For example, on stack overflow, when editing comments or posts, I often run into rate limiting where it tells me that I have to wait a bit before it will accept my edit.

There is no absolutely secure way to store credentials in a client. The most common scheme for credentials is to require username and password (securely over https) and then when that is accepted on the server as legit credentials, some sort of token is issued to the client which can be used for future API calls. That token may be in a cookie or may need to be manually included with each subsequent API call (the advantage of a cookie when using APIs from a browser is that the cookie is automatically sent with each subsequent request).

If the token is a cookie, then the cookie is stored in the browser's cookie storage and an expiration can be set for it. The browser's cookie storage is protected from access by web pages from other sites, but can be accessed by someone on the local computer (it's stored in the file system).

If the token is not a cookie, just returned as a token, and the client wishes to store it, there are a few other places that Javascript provides access to in order to store it. Local storage has similar security as cookie storage. It is protected from access by other web sites, but can be accessed by a person on the local computer.

jfriend00
  • 683,504
  • 96
  • 985
  • 979