I have a API in Express.js that will create blog posts and add them to my database. When I make a request from my React app inside of DevTools it will show my JWT. I am worried that when my site goes live people can see my token and make a request from their site to add unwanted posts. Please tell me what is going on and how I can prevent the security error.
When you send a request with a token in the header it will look like this in the header pane in Developer Tools:
I assume that's what you are wondering whether is safe or not.
The connection between the React app and the API is unencrypted when you are using ordinary HTTP. That makes a replay attack possible – an ISP or another server between the front-end and the API can read the token and pretend to be you later on with the read token.
The most important solution to that is to use HTTPS, which is encrypted HTTP. Potential attackers are unable to sniff and steal the tokens when you are using HTTPS. When you are dealing with usernames, passwords, etc., you should always use HTTPS.
HTTPS is free to use and not very hard to set up. See here for more details. There is also an interesting discussion here that you might want to read.
it's possible to see the JWT on the Chrome Dev tools because you are sending it as authorization header when creating a new blog post on your API, and you are making this request directly from the React application.
If the JWT is sensitive it should never be available on the front-end, you must have a server acting like a proxy, it should receive the request from the React application and then forward the request with JWT as the authorization header to your API.
Doing that you would avoid leaking the JWT, but it would still possible for someone to make requests to your proxy, which will be forwarded to your API.
If you want that only your react application be able to perform requests to your proxy, you could create a middleware which verifies the IP address of the incoming request (more details here), if it matches with your React app address then you accept the request, otherwise, you return a non-authorized error.
If you want only specific people to be able to create blog posts, then you should put authentication on the react application.
Related
I've been studying the OAuth 2.0 authorization code flow and am trying to write a React application with an Express backend that displays what a user would see on their own Instagram profile. I'm trying to do so with minimal external libraries (i.e. not using passport-js) and without bringing a database into the mix.
This is my flow as of now:
Resource owner clicks an <a> tag on the React application (port 3000) which redirects them to the /auth/instagram endpoint of my Express server (port 8000)
res.redirect(AUTHORIZATON_URL) sends them to Instagram's authorization server
Resource owner consents and the authorization code is sent back to the predefined redirect-url /auth/instagram/callback with the authorization code set as a query parameter
I strip the authorization code off the url and make a POST request to https://api.instagram.com/oauth/access_token to grab the access token
Now that I have the access token, how do I reach out to the React frontend to let them know that everything worked and that the user was successfully authenticated?
From what I've read, this is where the idea of sessions and cookies come into play, but I haven't had luck finding documentation on how to achieve what I want without bringing in third party libraries.
In the end, I would like for my app to support multiple users viewing their profiles simultaneously. Since I imagine passing the access token to the frontend defeats the purpose of securely retrieving it on the backend, I'm guessing I will somehow need to pass a session id between the frontend and backend that is somehow linked to an access token.
Any ideas as to what my next steps should be are greatly appreciated, as well as any articles or documentation you see fit. Thanks!
Since you're doing the OAuth authentication on the server side, you have to pass some parameter to the redirect_uri, identifying the user session (see: Adding a query parameter to the Instagram auth redirect_uri doesn't work? );
When the redirect uri is called from the authority server, you will know which user was authorized. To notify the browser there are two options: 1) Notify the client using web sockets; 2) Pull the state from the client using a timer triggered function;
Help me to understand how to implement proper security for web and mobile apps, which would be enough for my case.
What I have:
Backend. Some sort of Stateless REST API, which consumes and produces JSON text. Does not store any kind of state.
Web application. Main portal to the service functionality.
Mobile applicaiton. Provides a reduced a set of functions to users of the service
I am not going to store any state on the backend. Instead, I am going to delegate this to both mobile and web browser applications.
Now here comes the question of security. How do I properly secure that?
Since session mechanism does not really work for me, I decided to go with JWT.
In my JWT I am going to store user Id and some other information like, for instance, user's privilegies.
For mobile app, I am going to send this token as a part of a response and the app will store it inside its secure store.
Each request it will send this token as Authorization Header.
For web app, I am going to send this token via HttpOnly cookie. This token, thus, will be included in every request from the client.
The problem now is a possible CSRF-attack. To address that I thought of the following. Each user "session" will be associated with CSRF token.
Since I can't store this token on the server (remember, stateless API), I can send it as encrypted (again, with JWT) token to the client via HttpOnly cookie and non-crypted in a regular cookie.
Now, every request the web client will use non-crypted token from the cookie and send it back to the server. The server will check if this token matches from the Encrypted one which is stored in HttpOnly cookie.
Also, I am going to use different URL endpoints for web and mobile web apps. What for? In order to keep auth mechanisms described above separate - I believe this will help me to keep the service secure.
Do you think it is an OK solution? What problems do you see here?
Thanks in advance.
In general, what you described looks good and pretty standard. However, if I understand correctly, the CSRF protection is flawed.
To make sure I understand correctly: a csrf token would be stored in an encrypted httpOnly cookie, only to be sent back to the server as reference. Another cookie would have the same value but unencrypted, in a plain (non-httpOnly) cookie, and the server would compare these two. What's the point? An attacker would still be able to create a webpage to have a user make an request to your website, and both cookies would still be sent.
The reference cookie is ok to be in the httpOnly cookie for reference, but the other one should not be a cookie. It could for example be a request header value that you add to all requests. The client could receive it in a response, but not as a cookie. With jQuery in the web app, you can use the beforeSend hook to add it to all subsequent requests as a header. This way an attacker could not make valid requests from another domain.
I have created a simple REST api for my application using node/ express. I am using AngularJS on the front end to serve pages to the user.
I would like to add functionality such that the API can only be accessed via my front-end and anyone should not be able to do a GET/POST request to my site and get the data?
What strategies can I use to achieve this?
HTTP request can be formatted and sent to sever by many other means beside a browser (curl for example), so any server always detecting correct source of a request is not guaranteed.
The basic method to protect an endpoint would be to use some kind of authentication. The requesting client must present something uniquely identifying it. API should provide clients a token after it proves itself authentic (via login etc), and all subsequent requests would be checked for this token.
I recently read Cookies vs Tokens for Angularjs and implemented the sign in and authentication piece to allow users to sign in from a sign in page. The app is setup to have the account module (responsible for sign in's, account registration, profile, etc) as a separate page which will redirect to the SPA for the main application.
After successful sign on the token is sent back to the sign in page client as a JWT and the sessionStorage / localStorage values are set via js. Finally the user is redirected (also via js) to the main application. The issue is since I am redirecting via js the header can not be set, which obviously fails the auth in the main app when loading the page (Since my auth middleware is higher than both static and auth api requests). If I attempt to redirect from the server after a form post rather than returning the token via JSON on success, the sessionStorage will not be set via js as described in the blog post.
I've come to a couple of ideas and wanted to get input on which if either is good for best practice.
From the server set a response authenication cookie 'http only' (all our browser requirements allow this) cookie which is read on the next request to the main application. The cookie would then be read by the server and allow the secured static assets to be served. My initial thought was setting a cookie defeats the purpose of using a Authorization header on every request since there is a time the cookie could then be read even if it's removed on the first api request.
Allow the previously mentioned static assets to load without authentication (html, css, application js) and on the first internal API request (which in the application is required almost immediately on load) which will then have access through Angular's $http interceptors to set the request Authorization header. The same interceptor can then redirect to the sign in page if a 401 is sent back.
I thought the second would be a simpler approach due to only needing to move the auth middleware under the static file middleware and then updating the http interceptor in Angular, but thought it might be bad practice to have static files be able to load and then redirect after the fact. Any input is appreciated.
In response to your point 1
... My initial thought was setting a cookie defeats the purpose of using a
Authorization header on every request since there is a time the cookie
could then be read even if it's removed on the first api request.
The use of the authorization header is not mearnt to be mutually exclusive to the use of cookies. The idea is to use it when it best suits the problem like in single page applications and native mobile applications. However since it does depend on some kind of client storage, preferably sessionStorage, it is recommended to even sometimes use cookies for the purpose of storing the token if there are issues with the usage of sessionStorage like in old browsers. Hence as long as you use the cookie for storing the token but NOT for authentication, you have not defeated the purpose. Refer to point 1 in the follow up article
https://auth0.com/blog/2014/01/27/ten-things-you-should-know-about-tokens-and-cookies/
If you are wondering "but if I store the token in the cookie I'm back
to square one". Not really, in this case you are using cookies as a
storage mechanism, not as an authentication mechanism (i.e. the cookie
won't be used by the web framework to authenticate a user, hence no
XSRF attack)
I am building a mobile application that include users doing various things in the app and I started off with authenticating all user actions inside the app using a token that is stored locally on the device. My biggest concern was that anyone can sniff the network and look at the http requests I make inside the app and thus send false requests on behalf of a real user. Something like this:
http://mywebsite.com/postmessage?user=abcd&token=35sxt&msg=Hi
Now, I am using HTTPS though and no one can see my domain name nor the data being sent. So I'm inclined to get rid of tokens all together and do just this:
https://mywebsite.com/postmessage?user=abcd&msg=Hi
Am I correct in assuming I don't need tokens anymore? The whole purpose of them for me was making sure that no one can make an action on behalf of another user without authorization and now it seems pointless that I still use tokens. Am I missing something else?
Firstly, you were correct that having the token in the URL (or anywhere else) was a security risk over HTTP. However, now that you are on HTTPS, it should not matter whether you have the API token in the URL or you are transmitting it in some other way. The URL should be as secure as any other part of the transaction. I say "should" because in practice your internal infrastructure may do logging, metrics collection or reporting that reveals the URL slightly more easily than you intend. And the client may submit the visited URL (but not other info) to its own logging system or to a smart search service like Google, etc. But for most use cases and in most configurations this is not a major issue.
But it sounds from your question like you are talking about not removing the token from the URL and adding it to the HTTP headers or some other fashion, but actually removing the token concept entirely.
So what you should ask is, what is special about HTTPS that makes the token unnecessary? HTTPS secures the communication but it does not authenticate the client. Except in very unusual configurations, anyone can connect via HTTPS and issue commands, and unless you have some method of authentication the HTTPS will not protect you from unauthorized access. If you are using cookies for authentication, or if you are passing the token via HTTP headers (which is actually how I prefer to handle tokens when possible) then your need for authentication is satisfied and you do not need the token. If you do not have any other form of authentication, and you need authentication for security on your website, then you do need the token.
HTTPS is basically used to ensure that you are communicating with a webstie that you intended to and to encrypt communication data so that even if someone intercepts your data, it makes no sense to them.
For e.g. if you are placing an order on Amazon and making a payment,
HTTPS will ensure that:
you are actually submitting payment details to Amazon
your payment data is encrypted when flowing from your browser to Amazon webserver.
When communicating over HTTPS, browsers validates servers digital certiifcate to confirm their identity , then a key is exchanged between server and browser to encrypt data flow between browser and server.
By default HTTPS does not authenticate client. So if you have some actions specific to particular user, you still needs authentication token from client.
But if the token is passed as query parameter in URL itself, then it is still exposed to attackers, so send the token in cookie over HTTPS.
It is also recommended to mark your cookies as secure, to ensure that cookies are sent only over a secure (https) connection and not over http as it can reveal user details.
Hope it helps.