I've been learning about how to use Keycloak from React (with the Keycloak javascript adapter) with the scenario that Keycloak will provide SSO, allowing the React application to authenticate users with Keycloak, and then use the access JWT provided by Keycloak for bearer authorization with some secured REST api.
I have read lots of discussion on Stack Overflow about where is the best place within React to store the JWTs that Keycloak provides when the user is first authenticated (i.e. context / redux / local storage / cookies). However whatever choice you make about storing a JWT there is always a risk of a XSS attack and the token therefore being obtained by someone else. Because you'll be storing a refresh token as well as the access token, if these are both at risk of being compromised then that would be less than ideal!
Thinking about this I'm wondering if it's actually possible to not ever need to store these tokens in memory at all. I am wondering if the following scenario woud work, and if so (1) is it a better security approach or have I missed something, and (2) are there any disadvantages to it?
The plan is this... When the user first runs our React application we authenticate the user via Keycloak, which might require a login / authentication process. React gets the response back and only extracts and stores from the response the parts that the React application needs to operate, such as some user information and resource roles. But we won't store the JWTs, instead we will instantly discard them.
When the React application subsequently needs to make a rest call it first will re-authenticate the user via keycloak, which will be a seamless / non-visible process from the user's point of view, as they are still authenticated as far as Keycloak is concerned. (On that last point I'm guessing that this is done by a session cookie from Keycloak?). Keycloak will respond to the react application with the tokens, we extract the access token and use it to make the required rest call, and then the React application can discard the token immediately after it has been sent to the server.
Have I come up with a genius idea, or is this seriously flawed???
I'm developing the restful web app that using some popular web framework on the backend, say (rails, sinatra, flask, express.js). Ideally, I want to develop client side with Backbone.js. How do I let only my javascript client side interact with those API calls? I don't want those API calls to be public and be called by curl or simply by entering the link on browser.
As a first principle, if your API is consumed by your JS client, you have to assume, that it is public: A simple JS debugger puts an attacker into a position, where he can send a byte-for-byte identical request from a tool of his choice.
That said, if I read your question correctly, this is not, what you want to avoid: What you really don't want to happen is, that your API is consumed (on a regular basis) without your JS client being involved. Here are some ideas on how to if not enforce, then at least encourage using your client:
I am sure, your API has some sort of authentication field (e.g. Hash computed on the client). If not, take a look at This SO question. Make sure you use a salt (or even API key) that is given to your JS client on a session basis (a.o.t. hardcoded). This way, an unauthorized consumer of your API is forced into much more work.
On loading the JS client, remember some HTTP headers (user agent comes to mind) and the IP address and ask for reauthentication if they change, employing blacklists for the usual suspects. This forces an attacker to do his homework more thoroughly again.
On the server side, remember the last few API calls, and before allowing another one, check if business logic allows for the new one right now: This denies an attacker the ability to concentrate many of his sessions into one session with your server: In combination with the other measures, this will make an abuser easy detectable.
I might not have said that with the necessary clarity: I consider it impossible to make it completely impossible for an abuser to consume your service, but you can make it so hard, it might not be worth the hassle.
You should implement some sort of authentication system. One good way to handle this is to define some expected header variables. For example, you can have an auth/login API call that returns a session token. Subsequent calls to your API will expect a session token to be set in an HTTP header variable with a specific name like 'your-api-token'.
Alternatively many systems create access tokens or keys that are expected (like youtube, facebook or twitter) using some sort of api account system. In those cases, your client would have to store these in some manner in the client.
Then it's simply a matter of adding a check for the session into your REST framework and throwing an exception. If at all possible the status code (to be restful) would be a 401 error.
There's an open standard now called "JSON Web Token",
see https://jwt.io/ & https://en.wikipedia.org/wiki/JSON_Web_Token
JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for
creating tokens that assert some number of claims. For example, a
server could generate a token that has the claim "logged in as admin"
and provide that to a client. The client could then use that token to
prove that they are logged in as admin. The tokens are signed by the
server's key, so the server is able to verify that the token is
legitimate. The tokens are designed to be compact, URL-safe and usable
especially in web browser single sign-on (SSO) context. JWT claims can
be typically used to pass identity of authenticated users between an
identity provider and a service provider, or any other type of claims
as required by business processes.[1][2] The tokens can also be
authenticated and encrypted.[3][4]
Set a SESSION var on the server when the client first loads your index.html (or backbone.js etc.)
Check this var on the server-side on every API call.
P.S. this is not a "security" solution!!! This is just to ease the load on your server so people don't abuse it or "hotlink" your API from other websites and apps.
Excuse me #MarkAmery and Eugene, but that is incorrect.
Your js+html (client) app running in the browser CAN be set up to exclude unauthorized direct calls to the API as follows:
First step: Set up the API to require authentication. The client must first authenticate itself via the server (or some other security server) for example asking the human user to provide the correct password.
Before authentication the calls to the API are not accepted.
During authentication a "token" is returned.
After authentication only API calls with the authentication "token" will be accepted.
Of course at this stage only authorized users who have the password can access the API, although if they are programmers debugging the app, they can access it directly for testing purposes.
Second step: Now set up an extra security API, that is to be called within a short limit of time after the client js+html app was initially requested from the server. This "callback" will tell the server that the client was downloaded successfully. Restrict your REST API calls to work only if the client was requested recently and successfully.
Now in order to use your API they must first download the client and actually run it in a browser. Only after successfully receiving the callback, and then user entry within a short frame of time, will the API accept calls.
So you do not have to worry that this may be an unauthorized user without credentials.
(The title of the question, 'How do I secure REST API calls', and from most of what you say, that is your major concern, and not the literal question of HOW your API is called, but rather BY WHOM, correct?)
Here's what I do:
Secure the API with an HTTP Header with calls such as X-APITOKEN:
Use session variables in PHP. Have a login system in place and save the user token in session variables.
Call JS code with Ajax to PHP and use the session variable with curl to call the API. That way, if the session variable is not set, it won't call and the PHP code contains the Access Token to the API.
I have an API that I want to make a request to from my frontend, which is built using React. However, I don't want anyone to be able to see the API call in my code, because if someone just opens the inspect window, then they can see the API call. I've thought of perhaps adding some sort of header to be sent as authentication in the request, but that doesn't work either because you can just see the code if you inspect the site.
How would I do this? My API returns a private key that I can't just store in a variable directly within my code.
Sorry if this question doesn't make sense, but I appreciate all the help.
Your frontend code is insecure and observable by default. There is no secret in the frontend.
If your API returns confidential data that should only be accessed by the appropriate user you will have to implement authentication of any sort.
A user would then for example provide a password in order to call the API or he logged in before and got a token (e.g. JWT) that he sends with every request to authenticate. There is a user identity on every request then and your backend can decide if the user is allowed to get that private key.
If you really really want to make it difficult for someone to see your frontend code your router might provide a feature like "protected routes" that require such a token in order to access certain routes of your application. It will still always be possible to get the frontend code because the business logic has to stay on the backend.
I am new to web authentication and need some clarification.
I have seen people implementing token based authentication alongside angularjs $rootscope to save logged-in user information.
Why need to attach a token to Headers at every request if the angularjs application will only check its own variable to identify that the user logged in?
Likewise, if one has a token in every Headers, why simply check the Headers on client side to know if the user has logged in? If so, I do not see why one uses $rootscope to save logged-in user's info.
Thank you in advance.
I think you unintentionally nailed it when you said "the angularjs application will only check its own variable to identify that the user logged in".
The frontend will usually just trust that whatever kind of token it has is valid, since there is no way to do an independent verification of it (remember, there is no such thing as frontend security). The backend however can't do that, it needs to actually verify on each request that the user is who he/she claims to be, otherwise your application is not secure. Hence you send the token on each requests so that the backend can check it.
If you simply trusted the frontend to say who is logged in or not then nothing would stop an attacker from simply bypassing that check using javascript and take control of any account they wanted. Validation always needs to be done backend.
As for saving it in rootScope, that is mostly just a convenience thing people do for things they always want available so they don't need to get the data in all controllers. I tend to use an abstract state in ui-router or a shared factory for that instead, but it amounts to mostly the same thing.
I need some advice regarding using session tokens to authenticate users. I am building an AngularJS app which uses an API to tie in with the backend. I am only building the front end, not the backend. The documentation states that all calls to the API have a session token attached in the body of the request (POST).
I would like to know about the security of storing this token in localStorage. That is where I am storing it now and retrieving and attaching it to each API request. After login, the server sends the session token in the body and I save it from there.
There is no documentation about an x-access-token header that should be sent with the request made to the server. It is not being checked server side. What are the implications of this? I feel that it is susceptible to attacks without this added layer of security.
My main concern is the security of this setup. I want to know what the best setup is to make sure this app is as secure as possible and recommend changes to the way the backend is setup to facilitate this.
Thanks!
As you tell, you are only working on the UI part and not the backend. It is up to the backend team to ensure headers are properly evaluated and security is enforced (btw request headers do not belong to request body). Just put the token into the x-access-token header as they tell.
Storing the token inside the localStorage gives you a little more control over the cookie: You will not accidentally send it to unnecessary URLs. However, older browsers do not support it - you may need to use a shim for that.
In a case of SPA, you may consider not storing the token at all: It could be fetched each time your application is accessed and then stored within a service in angularjs, but it depends how your fetch/login operation is implemented (is it always interactive, how long does it take, etc).
I would suggest use $cookies rather than localstorage. As localstorage does not support some legacy browser.
I am using cookies to store token in my project