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.
Related
I have looked through quite a few tutorials (e.g. this, this, and this) on user authentication in a full-stack Django + React web app. All of them simply send username and password received from the user to the backend using a POST request. It seems to me that, if the user leaves the computer unattended for a minute, anyone can grab his password from the request headers in network tools in the browser. Is this a valid concern that must be taken care of? If so, how should these examples be modified? A tutorial / example of the correct approach would be appreciated.
It seems to me that, if the user leaves the computer unattended for a minute, anyone can grab his password from the request headers in network tools in the browser
If the user leaves the computer unattended then what you are describing will probably be the least of his/her worries.
Authentication is a complex topic, if you really do not want to use existing libraries that handle this for you then you will need to spend quite some time to get things right (knowing that even then, risk 0 does not exist), the most basic thing being to never store plain text credentials on your DB and using https to transmit them over an encrypted connection. You can then start thinking about JWTs, avoiding local storage, CSRF and securing cookies, refresh tokens, etc.
You cannot do much however about cases like the one you describe of people giving away access to their computers or sharing their passwords with others except reminding them they should never do such a thing.
On a side note, if the user didn't have the network monitoring tool open when making the request to your website, opening it afterwards will not show the previously submitted plain text credentials (there are workarounds to this however)
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.
I'm looking for some information about a problem that I never thought about, and that I can't find much on the internet (or I'm looking wrong).
Here it is, for a dashboard project in my company, I need to be able to set up a system to store one account per client, or I just have to click on the account in question to connect, like twitter, google or instagram for example.
After the person has added his account, it appears in a list that can switch whenever he wants. Only I don't really see how to set this up, storing the login information in the localStorage? or the jwt token? I confess that I can't find a correct and secure solution as it should be, that's why I'd like to know if some people would have already done that, or if I can be oriented on an interesting solution?
Thanks a lot!
(Sorry for my english, i'm french and it's not perfect ^^)
Do not use localStorage. LocalStorage is not secure at all and can easily be hijacked through any js code running. If you need to store sensitive information, you should always use a server side session.
When a user logs into your website, create a session identifier for them and store it in a cryptographically signed cookie. If you're using a web framework, look up “how to create a user session using cookies” and follow that guide.
Make sure that whatever cookie library your web framework uses is setting the httpOnly cookie flag. This flag makes it impossible for a browser to read any cookies, which is required in order to safely use server-side sessions with cookies. Read Jeff Atwood's article for more information. He's the man.
Make sure that your cookie library also sets the SameSite=strict cookie flag (to prevent CSRF attacks), as well as the secure=true flag (to ensure cookies can only be set over an encrypted connection).
Each time a user makes a request to your site, use their session ID (extracted from the cookie they send to you) to retrieve their account details from either a database or a cache (depending on how large your website is)
Once you have the user's account info pulled up and verified, feel free to pull any associated sensitive data along with it
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.
I have an angularjs app that is on a separate domain than my backend, and the users from my backend all have roles and permissions that allow them access to various areas and elements of my frontend.
Before, I was just storing to a cookie and checking as I needed through the use of angular services and whatnot, cool.
Now the permissions datum have reached the point where they are too big to store in a cookie in the browser. And I'm avoiding Localstorage for fear of user tampering.
The Question:
How do I store the users sensitive data (or anything sensitive, really) that are too big for cookies on the client side in a manner that is safe and doesn't require API calls all the time to get?
I don't want to have to phone home every page change to get this data direct from the server when I need it, because I feel this would be really detrimental to the speed and flow of the site, not to mention the frequency at which this would need to happen would be ridiculous for my app.
Keep in mind that I do proper permission checking on the backend before carrying out any actions, but I'm more concerned about users tampering with their permissions to show certain elements that were removed on the frontside before.
What would be your solution or your advice on this?
If it ends up on the user's computer, regardless of whether it's in a cookie, in local storage, in the URL, in the browser's cache, or anywhere else on the user's computer, assume that the user can see it and mess with it. (You could encrypt it, but if your client-side logic knows how to decrypt it, you're back to step one.)
The best that you can do is exactly what you've described - be sure that the server only carries out authorized actions, and never trusts what the user tells it.