Best practice: Sending Twitter access token to server - reactjs

I am using NextAuth to login users using Twitter. This works fine and I receive the AccessToken and the Token Secret on the client side. However I need to query the Twitter API on the server side to get the logged in user profile information. Therefore I need to submit the AccessToken and Token Secret to the server with every request.
Should I combine the AccessToken and Token Secret into one string and send it as part of the Authorization Header parameter and parse it on the server side?
Security wise what would be the recommended way to send the access token information to the server?

I don't know if there's a best practice, but I'd say there are some thoughts that would argue against some of the solutions available.
First of, from a terminology standpoint, using the Authorization header would seem to be a misuse of its defined purpose (RFC 7235):
"... allows a user agent to authenticate itself with an origin server"
And:
"Its value consists of credentials containing the authentication
information of the user agent for the realm of the resource being
requested."
In this case, that's not what you're doing - the supplied credentials are not for the requested resource (action, rather), but information needed to by the requested action.
Secondly, I'd refrain from including any of the credentials in the path, for the reason that it's usually not treated as sensitive information from a logging perspective.
Since you're thinking security, I just assume you're enforcing HTTPS with your Functions. I also assume you're using HttpTrigger since you're saying you need to send the credentials with each request.
As I see it, you have 3 options:
Put it in a custom header (not Authorization)
Put it as query parameters
Put it in the body
Personal guidelines for the 3:
Header values as "meta" associated with the request that won't fit as query (or in URL).
Query parameters as parameterized "meta" associated with the resource/action.
Body as information to be used in processing an action (e.g. the state of a resource to be created).
So... I'd put it in the body.
All 3 options are secure (or well, as secure as the sever is configured). My best guess is that the body is the least logged information on a server. Primarily because the body can vary greatly in size, and would take up a lot of space if all request bodies were to be logged. Some servers might log the full URL (including query parameters), which is definitely a thing to take into consideration. Whether Azure does this "behind the scenes" for Functions, I don't know. The path is available as clear text via Application Insights, the query parameters are as far as I know not shown anywhere, unless explicitly written to the log by the implementation.
In any case, base64 encoding the information could be a last "good practice" step regardless of your choice, for example as "value:value" like BasicAuth.

Related

I want API JSON response data but don't want it to be shown in network tab as its not specific to logged in user yet very sensitive?

So basically I have some information which I have gathered with lot of effort, this information is not specific to user so I cannot totally depend on my user logged in token, this is somewhat some generic info that needs to be present on the website as info and currently this information is coming directly as JSON from API calls in network tab which makes me insecure that this info can be copied and used by 3 person without my concern.
What can I do to stop this ?
The only foolproof way to keep the client from possibly being able to see and possibly manipulate sensitive information is to not send it to the client in the first place. There's no other way. While you can make it harder for the client to do so by, for example, encrypting on the server and decrypting on the client side inside long, convoluted, minified code - it's still possible.
If each user has information specific to them that you'd like to display, the right approach would be to validate the client's login token and then send back the data for that user (but not the data for any other user). If the client sees that the information is incorrect (like if someone else was using the computer), you can prompt them to log out and log back in with their actual credentials, resulting in another request that'll be verified by the server and which will return the data needed to display what the user is looking for.
If you're worried about third-party snoopers, you should also, of course, use SSL on your site. (Unfortunately there's not much you can do about other vulnerabilities the client may have, such as malicious browser extensions, drivers, and hardware - either don't send the info in the first place, or bear the small risk.)

Secure an API route without credentials

I have a form that checks if an email is already in my DB (/api/user?email=user#example.com), if it does, it responds with their information.
I can't seem to find a way to protect my API routes from someone going to postman and just brute forcing GET https://example.com/api/user?email=name#domain.com and collecting personal information.
I need this functionality without any login credentials. I know there must be an industry standard way of doing this. There are insurance providers that do this with their forms. (e.g. once you enter your email, is greets you with your name and asks you to finish filling out a form.)
In other words - I need my api route to somehow differentiate between a legit browser making those requests or someone with different intentions.
There is no standard, but you can protect your route from brute force:
Add rate limiting to avoid brute force from small range of IP's
Add captcha check to avoid non client side requests and cheap bots.
Generate session (or hashed url) for each user and allow only user's with session to complete form by entering email
Use csrf token to avoid non client request
Without credentials there is no 100% bulletproof way of verifying an authentic request from a user versus one from someone or somewhere else. The "industry standard" is a certain level of personal data that can be exposed without any verification, as your example with insurance providers mentioned.
There are some ways to mitigate this, such as by checking the request headers; specifically origin, referrer, user-agent, etc. but all of these could still be bypassed if one really needed to. If I were in your place, and "absolutely had to have no credentials to validate the request", I would just return only a shallow amount of information such as an email and first name, which is essentially the same amount as anything else.

Can the client modify react component state?

I'm building an admin page for an application and have a state value 'authenticated' that flips from 'false' to 'true' after a successful login (which is authenticated on the server) which then shows the actual admin panel.
Are component state values safe from tampering by the client? Basically, if the client can modify my 'authenticated' state value to 'true', they can skip the login and go straight to the admin panel (which I obviously don't want).
I read that React Dev Tools allows the client to modify values yet everyone says "validate on the server" but I am validating on the server and updating my state accordingly, if the user is approved. If it is not wise to have a state value manage this, what is the right way to conditionally show the admin page after a successful, server-side authenticated login?
I think this is an important question since tampering with state values in a React app can have huge negative consequences on data integrity within an app/database.
TL;DR: Either require an authentication token with every request or require authentication through a session.
Never trust users always. One potentially big issue is if you "hide" admin actions behind the admins page without requiring authentication.
For example, assume the backend server uses a REST API to accept commands. In the admin panel you get links to administrative actions like a button 'Delete Everything' that sends a DELETE request to server.net:8080/api/admin/everything without requiring any authentication. If you're a user, you can find that in the code potentially and then send a DELETE request to that address from anywhere without any repercussions.
We'd never give administrative privileges to anyone who would want to delete everything... Because we'll never untrust someone. Right?
Worse, someone might find the server and fuzz some inputs to it, and oops! They manage to delete everything (or even worse, GET everything stored in the database). This wouldn't be hard to do, especially if the server you use to authenticate is the same server you use to issue commands. History has proven "security through obscurity" to be a very bad paradigm. Every action should be authenticated, even if it seems like the actions will be hard to find.
Generally, providing a JSON web token or some other form of authentication token and having the user send that with every request is a good start at least, especially if it has an expiration date. The token would be provided through a separate request with valid credentials.
Sending a token with every single request obviously isn't ideal. There are a couple of other things to try. For servers using PHP, you can probably trust sessions (though very many people who know more than me would probably disagree). In more modern cases, you could try to use Web Sockets, requiring the token after connection. Then only after authentication with the token do you allow the user to make administrative requests.
That way, even if a user knows the exact command they can send to perform any action, the server won't let them without a current session or token. Unfortunately, unless you're already using Web Sockets or depending on a session, it will likely require a lot of changes. I'd consider this to be critical though.
It is always possible to tamper values in the front-end, there is no way you can rely solely on the front end to ensure security.
Your best approach is to implement some form of authentication and authorization on your backend. In this way, even is some users pretend to be admin, they will be blocked when you do the next request to the server.
Perhaps if you can send more information regarding your problem, we can think of a more specific solution.

Angular - Can't see how to hide this API Key

I have the following code in my angular app declaration - an API key for Facebook (to implement Share button):
.run(function($FB){
$FB.init('9xxxxxxxxxxxx94');
})
So i know the general answer to this - 'API keys should be kept on the server side', however I don't see how i actually implement this.
The share call-method is made on the front end, so even if my server kept the API key and sent it, surely it's still visible on the front end, else how would the share button work?
So my question, how do I hide that Facebook API Key?
Thanks.
Requesting the key
The first thing that happens is that the client will request a key. This will only happen on certain pages like the sign up and log in pages. The idea here is that we want to make sure that only users browsing with a known client (in this case the official website or core client as it’s called) are allowed to take actions like creating or authenticating a user.
So when the client app requests the login page the server generates a unique token based on information sent in the request. The information used is always something the server knows, something the client knows, and something both know. So for example the server can generate a unique key based on User agent + current time + secret key. The server generates a hash based on this information and then stores a cookie containing only the hash on the client machine.
Setting permissions
At this point our key really isn’t a key anymore. It has been transformed into an access token. The server should then take this access token and store it for later retrieval. You can put the key in a database but since data of this type needs to be retrieved often I would suggest using a key-value store like Redis to cut down on database reads/writes and boost performance.
When you store the token you should also store a separate piece of data to indicate what permissions are associated with the token. In this case our token is acting only as a way to register and authenticate users so we store it next to a value that indicates who the token belongs to (the app’s web UI) and what permissions it has (limited to create and authenticate users). We treat it just like we would any other API client that way we can capture stats and control how it is used.
Authorizing a request
When the client then makes the POST request to create a new user or log in the server will check to see if the client sent an identifying cookie along with the request. If not, we reject the request. If it does send the cookie, the server should once again generate the hash using the values used previously (these values are either already known or sent with the request anyway so we’re not really taxing the server much) compare it to the cookie being sent to us, and if the values match allow the request to proceed.
Sources - Securing API Keys
OR
Simply send a request to your Server and let him handle your request with the hidden API-key and just return the result of your request to your front-end.

Securing Angular Application

I am creating an Angular application, and I am having trouble wrapping my head around the proper way to ensure my application and its users is secure.
I've been reading around many stack discussions, but I believe I am missing some core understanding of what is happening, please correct any errors you see written below.
So far I have a Sinatra server with many (currently mostly hypothetical) resource routes. A user can create an account using an email address and password that is stored in a database after being hashed with BCrypt. When a user logs in, the record is retrieved from the database by email and the password checked for authentication. It is from this point I am not sure how to proceed.
Prior to this I have simply set a session variable and had the server check that the variable exists in order to correctly route logged in users. Now my application is (currently) a single HTML page that uses Angular and ui-router to display different content, so most of the requests are simply returning JSON content.
It is my understanding that Restful applications should generally not use sessions, or rather that the server should respond identically to identical requests and not have its own data that shapes a response. But if I do not store something in a session variable, how could the server know that the client making the request has the correct permissions? And are sessions not stored in the browser anyway, thus not part of the server?
I believe from what I have read, it is possible to create a token which is essentially a large random string, return that string to the client and also store it in a database with a timestamp. The client then provides this token when making requests and the server hits the database to verify it exists and valid. But would the client not also have to store that string in a cookie? I suppose the angular application could store the token in a variable, which would persist while using the ui-router but not if the users navigates using the address bar.
I also do not understand how Basic Auth may or may not fit into this picture. Any help would be greatly appreciated, as well as a pointer to some good resources where I may find a better understanding of these concepts in general.
You want to read up on JWT. There are JWT libraries for Ruby and Angular.
I know you aren't using Node for your backend but a very easy way to see all the pieces working together is to run the angular-fullstack Yeoman generator. It uses JWT and the code is easy to follow.
As far as I can see, whatever you are doing with your sessions can work just fine.
This can be a sample JSON response from the server in case the user is not loged in :
{
"errorCode": 1,
"error": "User not logged in",
"data": {}
}
You can set your own error codes and handle what you want to do. You will send any data only if the user is logged in. For all the pages which don't require authentication, you can set data to whatever you want.
On the angularJS side, you can handle based on error codes, you can redirect the user to the login page and so forth.
The alternate way to support the same on multiple platforms is to use token based approach. The token based approach in simple words work this way.
The user logs in for the first time with his / her credentials.
The server verifies these information and creates a token from which the server is able to decode the user id.
Whenever the client makes the requests, it passes its token with every request.
As the server can decode the user information from the token, it sends or doesn't send the data based on whether that's a right token or not.
The token depends on a secret value. It can be same for all the users or differnet for each based on how you want to implement.
This is all done and you can look at
http://jwt.io/
As #andy-gaskell mentioned, you can look at
http://angular-tips.com/blog/2014/05/json-web-tokens-introduction/
I'm very bad at explaining. Please let me know if any of this doesn't make sense.
you are missing the point of the REST concept. One of the main concepts in the REST apis is that the server should be stateless - this means that you should not store sessions or other "state" in your web server. Every HTTP request happens in complete isolation. Every request should include all data needed by the server to fulfill the request.
But if I do not store something in a session variable, how could the
server know that the client making the request has the correct
permissions?
You can store request scoped variables. This means that they should be only active during the same request. You can store the current logged in user in the request scoped variable. In that way you can get the current user in your invocation of the business method. I'm not familiar with Sinatra but here is the doc: http://www.sinatrarb.com/intro.html#Request/Instance%20Scope
But would the client not also have to store that string in a cookie?
of course you should store your access token in the client side
https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/
as #Andy Gaskell suggest take a look at JWT and fullstack application code generators and forget about the basic auth because it's really "basic".
more useful links:
If REST applications are supposed to be stateless, how do you manage sessions?
http://www.sitepoint.com/php-authorization-jwt-json-web-tokens/

Resources