I trying to store extra fields in cookies with ASP.Net Core Identity.
one of this fields, is Role Name.
Is it safe to store role name in cookies?
For example, is it possible that user change role name from "normalUser" to "admin"?
I am using ASP.Net Core 3.1 version.
NEVER store sensitive data in cookies. As mason said in the comment, cookies can be modified meaning they can be exploited. And besides, your cookies might be in plaintext, which is even worse.
I would recommend storing such data securely in the backend.
Sessions are definitely safer than cookies since they are stored on the server side but they also can be subject to attacks (session hijacking). You'll need to properly configure them for better security.
Related
In an angular 10 App, after user authentication, some sensitive information was fetched from server side(like tokens used in another Api). And i don't want to store them in LocalStorage because it is too easy to find.
But i need to access to these informations from one angular service(let's call it ApiService), what is the best way to store these sensitive informations?
I think the essential question is, could Angular provide a way to store global variables in memory? (Like a static class in Java)
What do you mean by LocalStorage is easy to find? No other websites have access to LocalStorage items created by your site and anybody that has physical access to the machine can find anything that you store client side.
Use an Angular service that is provided in root and any component or service can request that service to access data stored in it. Provided in root means it will be a singleton and all requests for that service will get the same instance.
If you don't want a rouge library you have used or a XSS attack to have access to some information you need to store client side then a http only cookie is your only option. When a cookie is set as http then it will be sent back to node with each request but is not accessible via JavaScript on the client.
First of all, any sensitive information shouldn't be stored at the client-side, knowing that, jwt tokens cannot be hidden because eventually they will be sent at the headers of your secured API calls. and they are not considered as sensitive that in that matter. For that to be valid, you shouldn't encode sensitive data within your jwt token.
That being said, jwt security relies on the fact that although the tokens can be known/decoded, a third party cannot temper the token because they are signed using a private key/certificate that only the server knows about.
For the storage, you can use Angular singleton services to achieve in-memory sharing of global state between components, or use more sophisticated libraries to manage your application state (ngrx, akita...etc.)
I am building a node.js web application with react for the the GUI and graphQL served with Apollo for the back-end connecting to a RDS (MySQL) instance on AWS.
I am authenticating users and then returning JWTs. I have it figured out on how to renew/expire tokens, but now I am being faced with the question where to save it on the client side when a user visits the site...
There are two main concepts with a third being a hybrid model. 1) Store it as localStorage with JavaScript as described on HowToGraphQL 2) Store it in a Cookie with http-only set to true as described in the afore mentioned article as a cationary reference to Randall Degges
There is another alternative to store it in memory only on the client side but then a user would have to login every time the page is refreshed as it would not be persistent anywhere.
Concept 1 is vulnerable to XSS only if there is another XSS vulnerability already exploited. But it is secure to the site only so only scripts running on the site can access it and not scripts on any site. There it a lot of security talk that it should not be stored this way even though it is the common way because a developer cannot trust EVERY JavaScript script they are running on their site and there may be one that reads the localStorage and then sends it offsite.
Concept 2 removes the XSS vulnerable by declaring the http-only to only make it accessible to the server at your site. The problem here lies in that then a separate method has to be created to use the same backend authentication for other uses such as a standard API (for native apps or other sites) where the JWT is sent in the header over https where it is stored securely on another server.
So I researched and found this hybrid method described by Ben Awad 3) use a request token and a refresh token. The request token can then act normally for the standard API but then also on our react app site we can store it only in memory and store a refresh token in a cookie to send back a request token when users refresh or close and reopen browsers.
So theoretically, the best solution is Concept 3 which solves all of the concerns, but it is of course more complicated to setup.
My question: How worried should I be about opening up a JWT to an XSS vulnerability? It is something that down the road I would do the long way when I have more time, but I am pushing for a deadline. My site will be lesser known and not something like Facebook or Sales-Force that hackers would necessarily target. My site is not storing Credit Card data or other highly sensitive data other than a basic CRM and task list. If my site was open to XSS through other code, wouldn't the entire authentication process be vulnerable through keylogging scripts or the likes without even knowing the JWT. I feel like I would be doing a lot of extra work to secure against a possible threat that if occurred, the entire system would be compromised already.
If you are comfortable with your site to not work on Internet Explorer and some older versions of the major browsers, you can take advantage of a new cookies property, called Same-Site (to be more precise, the site will work but the cookie will not be secure).
By defining a cookie as HttpOnly, you are immediately secured from XSS attacks, but you leave yourself open to CSRF attacks.
Now by defining the cookie to have the property Same-Site=Strict, the cookie will be only sent through Http calls and only if the domain matches your site's domain. So for example, if someone creates a form in another site and tries to perform a post request to your own site, the cookie will be never sent.
If you want the cookie to be passed only on GET requests, you can set the Same-Site property to Lax but as you mentioned.
You can find more info about this feature in the following link under the SameSite cookies section:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
You should also check the browser compatibility of the feature by using the following link:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Browser_compatibility
This is the issue I spent a lot of time on. How to store the authorization token securely. People have different strategies in dealing with this so I will share what works for me. Users of my apps were targeted by different attacks, all of them where unsuccessful in stealing anything so far. None used XSS.
Here is what I do
In the end I opted for storing authorization token in local storage. Applications that I work usually have WebSocket connections on top of HTTP routes and I want the token to be saved in one place and act as a single source of truth. They are all web applications running in the browser. Most of the applications I build use JWT.
Why I do it like that
First why I don't use refresh tokens. If they are saved the same way as the actual authorization token would be saved negates the reason for refresh token to exist since the attacker can use the refresh token to get the authorization one.
Storing the token in cookies gives no benefits over local storage assuming that the app is secured against attackers being able to inject JavaScript into your app, mostly through forms and api on your app. Make sure all user inputs are JS injection safe. On top of that with cookies there are issues when using WebSockets that you must go around.
There is also the point of one of the accounts being hacked and you want to invalidate that token as soon as possible. JWT by default has no mechanism of being revoked. Implementing this feature negates the scalability of JWT because checking the JWT would require a call to the database to know if that user can do the specific action. There are 2 ways you can go about this. One is just check the user data if the user is frozen from the database, it is less scalable because of the call but if you already pull the user data in a middleware it is good enough TM. Other is to pull the the "is the user frozen" data from the database just when making changes to the database or when the call from the client is important.
In summary
I would store the token in local storage. Secure the app from code injections. And make a kill switch for the accounts if they get compromised in any way.
EDIT THANKS TO THE COMMENTS BY #JerryCauser
It is more secure to keep your token in a secure http only cookie. Don't expect a storage mechanism choice to automatically save your users from being hacked. There are ways to hijack sessions and other exploits including users using web extensions and approving their request to read protected data.
For the example of the betting website below, you wouldn't require user to write their password (or approve the request via automated email) every time they place a bet, but you would every time they want to take a withdrawal for example.
I use local storage because even if it happens for the token to be stolen, or another person got to your user's laptop (like a kid for example) you should never let the account do critical tasks without approval.
There is no magic bullet of anti hack protection. Try your best to keep your users safe with common sense.
EDIT AS ANSWER TO THE COMMENT FROM THE ASKER #amaster
If you are making a trip to the database on every call, maybe JWT is not the best solution. Point of JWT is to have signed claims and the id of the user without calling the database. In this case, maybe opt in for sessions instead of JWT.
Before I proceed with my answer, you may want to check out OWASP for a set of general guidelines regarding XSS and CSRF since you've mentioned cookies.
Cedomir already covered a good deal of the points with storing JWT client side. One thing that's worth mentioning is that if you have Third-Party scripts running in your web app, they also have access to the Storage API. So if a script you had loaded were to be hijacked, they could conceivably steal the token there. As for XSS with inputs, if you make sure to escape every possible user input, then that is largely mitigated as an attack vector. But you only have to screw up once for someone to take advantage of the hole and steal the JWT at that point. (Refer to this blog post for more details)
Now, if you instead store the JWT in a Http-Only, then you largely sidestep the XSS issue as you've already noted. However, now you introduced a new problem, that being Cross Site Request Forgery. Since cookies are sent with every request, a malicious actor could set up a website to make a fraudulent request on behalf of user and execute actions without the user's consent. Now I won't cover the mitigation in detail here as OWASP and other places have done a pretty good job already, but the short of it can be summed up by installing the most popular and well-maintained Anti-CSRF package for your language :-)
As for invalidating the token as Cedomir brought up, having that mechanism can be quite useful. However, to implement it does mean you give up some of the benefits of using JWT gives you. Whether you store the current JWT assigned to user and validate that or a unique key used to sign the JWT for each user, you now have user state to keep track of, eliminating one of the reasons to use JWTs. Depending on your application, you will need to weigh that tradeoff. A much simpler way could be simply to have short-lived tokens so that any token that is stolen potentially won't have a very useful lifetime. However, as you probably recognize a short lifetime would be a potentially a very annoying user experience. You could have your website periodically poll the server for a new token while your user continues to use the website as a way to improve the experience. You can also balance your security concerns with the lifetime of the token, like a 15 minute token lifetime for a e-commerce app vs. a hour or more for a social application.
I would however advise against the use of a refresh token, at least for a Browser-Based Web App. Typically speaking, the browser is just not considered capable of securing sensitive secrets. By using a refresh token, you're just deferring the stealing of credentials to another layer as by the nature of the refresh tokens, they're 1) long-lived and 2) effectively used as credentials to obtain more JWTs. So if the refresh token were to be stolen, an attacker can just get more valid JWTs on behalf of a user. If you have a mobile or desktop app, you have mechanisms you can use to securely store refresh tokens and this advice does not apply.
...Or you could just use sessions ;-)
When logging in on server set JWT token and a random csrf token in the httpOnly cookie
Also send this csrf token in body response of login back to client
On every future request from client send this csrf token via some header (eg. X-CSRF-TOKEN)
On the backend verify if the csrf tokens coming through the cookie and x-csrf-token are the same.
Then verify your JWT token and continue with your app logic.
Putting JWT token in httpOnly cookie prevents XSS attacks, validating CSRF token prevents CSRF attacks. Double sending csrf token in both cookie and header avoids storing stuff in the backend database.
XSS check
CSRF check
Stateless auth check
Auth doesn’t have to be over complicated. If you have clients that only want to pass JWT token in some header other than cookie then it’s better to just make a separate api endpoint for those programs.
While the question is not actually about OAuth / OpenID Connect I still think you can learn a great deal by checking out this Internet-Draft: OAuth 2.0 for Browser-Based Apps (Best Current Practice)
To sum it up: there simply is no secure way to store an access token on the client. If you develop only the frontend you pretty much have to use and store a token on client side - not because it's great but because you have no other choice. However, if you do have full control over Frontend and Backend you do have that choice and should think about using the same domain for both and use a session cookie as described in the Internet Draft. Basically the React application never even sees the acesss token, because your backend is serving a http page and handling the authentication directly, with the final step being a redirect back to your frontend while setting the session-cookie.
A potential XSS attack is pretty bad as it is and you should be careful not to introduce a vulnerability. The thing is: with the JWT-approach a XSS vulnerability leads pretty much to the worst-case scenario: the attacker is able to steal the user authentication and can impersonate the user - this is basically session hijacking.
The same attack against a regular session-cookie simply does not have the same impact (as long as the cookie uses the HttpOnly Flag which is highly recommended). Even though the vulnerability enables arbitrary JavaScript Code to run on the machine (which is really bad obviously) it's still a lot harder for the attacker to do some damage. He is not able to hijack the session in this case, because he is unable to read the cookie.
Just use HTTP only + SSL only cookies to save your JWT. It will make almost impossible to stole user's jwt via a soft or any type of code injections.
Someone said here, what it is no diff between LocalStorage and Cookies. He is not correct, bcs third party libraries and chrome extensions can easily stole LocalStorage data. But they cannot stole HTTP only cookie.
It will protect against any known and most likely new types of attacks.
JWT itself is completely protected. Just don’t store something there that could compromise your architecture or something like that (do not put a hashed password for example)
Upd: Good article about best practices for JWT strategy: https://ducktypelabs.com/5-mistakes-web-developers-should-avoid-when-using-jwts-for-authentication/
We've just had a security auditor flag our use of persistent cookies to maintain login state in our web application. As a bit of background, our web application is multi-tenanted, but no (or not many) operations are destructive. There may be - depending on the tenant - sensitive information available through our portal.
Back when we designed our application, we discussed the use of persistent cookies, and decided that we should based on usability. We didn't, and still don't to a degree, deem the information available as sensitive. Our users are fairly novice and we were more concerned with having hundreds of reset password requests.
Is the use of persistent cookies for logging in deemed a security risk? Is the trade off in usability even a discussion when we're talking about operational data of some fairly big businesses?
We haven't had any questions regarding persistent cookies before - not from any of our clients. Would it be worth implementing a 'tick to persist' that defaults to off to satisfy both sides?
Persistent cookies, are used for a variety of reasons, and to support numerous functionalities. If your app has absolutely nothing "sensitive" then, you can use persistent cookies for permanent authentication, and then issue re-authentication to access user account details, or do some changes (i.e. change password, or e-mail address). You mentioned that your users, are novice, so I don't think that they know that if someone else uses their browser they will also be authenticated without knowing his or her password (I would point it out to users).
But there is a reason why security critical apps like online banking, do not issue a persistent login cookies, although they could, because before making any changes to your account balance you have to re-authenticate out of band (via mobile, or some form of OTP). But it's considered insecure, and maybe it is because knowing someone's balance is already invading their privacy.
So if your app is not controlled by any government authority, and you're not bound by any law in your country, and you implement re-auth on sensitive parts of your app, then issuing 2-3 week persistent cookie for authentication, is not a significant security threat.
If persistent cookies are not to be trusted, Fatfredyy's suggestion sounds great.
However, if the problem is unsecure use of persistent cookies, why not encrypt them?
Upon either ticking "Remember me" or by default a cookie is generated including some unintelligible unique ID for the user and an encrypted part containing verification. The key to the symmetric encryption is stored in the DB with the user ID and never shared with the user. When the user revisits, you use the ID to access the key and decrypt the rest, verifying that no tampering has been done.
When an attempt to fiddle with the userid has been identified, display a message to the user and change the encryption key, requiring the user to re-authenticate.
This would enable you to use persistent cookies while not compromising the users.
I'm new to OAuth, and although I have scanned through many documents, I don't seem to have yet a good architecture / design to a secure web application, answering most/all of OWASP Top Ten
My newbie questions are
Why can't I just rely purely on OAuth? why do a user needs credential in my own application?
If I do, do I need hash / salt anything if I save it? I don't store any passwords, but what about tokens?
I still need to persist the users so they won't login everytime, (like in OS) - do I
Somehow use the OAuth token (save it? does it make even sense)?
Or use the plain old httpOnly secure cookie (if so, what happens if they log out of the Oauth provider? shouldn't I in this case ignore my cookie and let them log out?
How do I implement logging out? I can't force them to log out of the OAuth provider, and if I only delete the httpOnly cookie / invalidate their session locally, is that enough? and security issues?
How do I implement single sign on? I don't want the user, after approving to click again "log in using Facebook / Twitter / Google" I want an effect similiar to SO (page refreshes and "welcomes you back" what are the best practices to do that? Why does SO refreshes the page (I assume it has to do with the fact it needs to be client side, but I don't fully understand how it works to even know what to ask)
I guess I have a lot to learn, but reading on so many potential security issues, and having to master so many different topics seems like a good potential for me missing something that someone later will exploit.
Is using a framework such as Spring Security, or using Lift's built in user management going to save me all this headache? or do I have to know exactly what I am doing to avoid things like Session Fixation, Cross Site Request Forgery, Cross site scripting, Rainbow tables and other things I only remotely get...
Why can't I just rely purely on OAuth?
From a service providers perspective, OAuth is a means of controlling access of third party applications to the business logic. The end user does not have to give out his password to the third party app, and the access can be controlled. For example, the provider could restrict the access to only parts of the service for limited amount of time.
If you write a third party application, there is no strict need for you to have your "own" user artifacts. You can rely on the users that authenticate your application.
You could require that user's have an account with a provider such as Facebook or Twitter and not implement any password stuff yourself.
(You probably need some sort of artifact to represent a user, it should in this case contain information about how that user authenticates your application, for instance an OAuth token, or an OpenID URL).
If I do, do I need hash / salt anything if I save it? I don't store
any passwords, but what about tokens?
Just to clarify, in OAuth a token is typically both a key and a secret, and they are needed in cleartext to sign requests (there are differences here depending on which version of OAuth you use). So you can store them encrypted, as long as it is reversible for you.
I still need to persist the users so they won't login everytime, (like in OS) - do I
somehow use the OAuth token (save it? does it make even sense)?
Yes this makes sense, a token represents your applications access to a specific user's data. Save the token if you want to keep a "session" alive.
How do I implement logging out? I can't force them to log out of the OAuth provider, and if I only delete the httpOnly cookie / invalidate their session locally, is that enough? and security issues?
There is no concept of "logging" out of OAUth, a token either has an expiration time or not. You can of course "log out" by simply choosing to forget the token. The next time you will have to redo the authentication. You cannot force users to invalidate an access token, unless the provider has an API for that.
You could save the token in a cookie, but I would use other unique identifiers for the session you want to keep alive. You can persist the details of the tokens server side. The information you store in your cookie shold make it possible to retrieve the token you need.
How do I implement single sign on? I don't want the user, after approving to click again "log in using Facebook / Twitter / Google" I want an effect similiar to SO (page refreshes and "welcomes you back" what are the best practices to do that? Why does SO refreshes the page (I assume it has to do with the fact it needs to be client side, but I don't fully understand how it works to even know what to ask)
If you save a token in a database, save an ID for that token in a nice secure cookie. When a user goes to your service, use the information in the cookie to make a call from your service, to the service provider, to check if the token is still valid. If so, you have established enough trust for you to "log in" the user in your application without having to go through the pain of the OAuth process again.
And as a side not, StackOverflow uses OpenID and not OAuth for user authentication. OAuth can be used for the same purpose but is mainly a specification for application authorization.
I hope this helped, and don't sell yourself short. This site is for posting questions, not for appearing all-knowing.
I asked a similar question here a while back but all the answers were offering OpenID which is nice but it doesn't work with services that require authentication that don't use it (such as EventBrite).
Say I want to create an app that lists your events from event brite, and their analytics (which eventbrite includes). Any person can sign up for this service to list their events. But since EventBrite doesn't have OpenID to authenticate, I need to somehow get the user login and password to EventBrite.
Some possible solutions are:
Store credentials in YAML like this. Easily hackable.
Have user enter in credentials into a form on my site, I save the credentials to my database, and use them to login to EventBrite. Easily hackable.
Have user enter in credentials and I pass them directly to EventBrite without saving, and I save the response header Cookies to the database, and when they expire, have them login again. Is this easily hackable?
This hypothetical service also wants to automatically check events (say via cron), so it doesn't depend on the user going to my site via the browser. So cookies or credientials need to be stored somewhere.
The thing is, after asking this similar question about confidentiality and security it sounds like you should never build an application that does what I'm describing. There's got to be some way building something like this is okay.
What is that way? What am I missing? Is it okay to go with #3 and save the cookies (but still needing the user to submit their email/password via a form which I send to Eventbrite)? What is an acceptable solution to the problem?
There isn't a secure way to do this. You can employ workarounds, but that's about it.
Storing passwords in YAML or XML in cleartext is definitely out
In fact, even encrypting and storing passwords is wrong. Your application would need a way to decrypt the passwords, so the attacker can also decrypt the passwords.
The recommended way to store passwords is Salt + Hash, but because it becomes unrecoverable, it is useless in your case.
Because of 2 & 3, no matter where you store the users credentials, you are vulnerable.
Storing the cookies instead of the passwords is a better idea. But again, this involves the password going through your website, which isn't good.
Given your situation, storing the cookie is a better approach. Use HTTPS throughout, even on your website. Its less than ideal though, and you and your users should be aware of it.
Eventbrite has recently release new documentation describing how to implement OAuth2.0 for cross-site user authentication.
I would recommend using our javascipt-based OAuth2.0 widget, which stores the user's authentication tokens in their browser's localStorage by default.
Since the auth tokens are stored in the user's browser, and are prevented from being accessed by other domains, it's not likely that there would be any security leaks.
The need for email and password combos are completely avoided in this authentication scheme.
Most sites only support direct login with the original cleartext password, so you have to get, store and provide that too. And I would never ever trust you with that.
The problem with your concept is that you require the password to be given to a third party. The solution is not to involve a third party, for example my browser is pretty good at storing and filling in passwords for me automatically (my hard-drive is password protected too). And they are dozens of other password wallet apps too. I wouldn't gain anything by subscribing, using your service.
Before going into such a business, consider you are going to be the #1 target. Facebook, Google are incredibly paranoid about security, spending a lot of time, money and effort to keep the logins safe. Do you have the same resources? Then you are a better target. Also by hacking your service, they immediately get multiple accounts, passwords of your users, also seeing who is always reusing its password.
For working with the Eventbrite API, I'd recommend ensuring that all connections are over SSL, and that you authenticate using a user_key rather than a username and password.
More information about authentication for the Eventbrite API is here: http://developer.eventbrite.com/doc/auth/
After logging in, users can find their user_key here: http://www.eventbrite.com/userkeyapi
This should prevent username and password information from being intercepted over the wire, or read from a local data store.