Workaround for auth without OAuth/localStorage - javascript

I'm relatively a newbie to extension development for chrome, i find that there is a lot of source material out there which mention the use of OAuth over localStorage. I need to verify credentials for an API that doesn't offer OAuth. I don't want to do it through localStorage either due to the obvious security risks. Is there any other best practices that could be followed ?
As of now I am directing the client to the main website through which Basic Auth occurs. If I were to follow this way the client would login through the website everytime and I don't know how to check the ifLoggedIn() status other than through accessing the domain through a dummy request and checking if a 401 is returned. Is there some way out for this as well ?

Even if you use oauth, in the google samples it still saves the tokens in localStorage. Chrome storage is not encrypted but the only way to get to it is by having access to the machine (physical or by malware) in which case you can't do much. Even if it were encrypted, malware could reverse eng. it since the keys are in the client.
The only encrypted area currently is chrome.sync but the user has to enable it plus it seems more dangerous to me. Anyone that hacks into your chrome password could login to chrome from another machine and receive the encrypted sync data. That's worse because it doesnt require malware or physical access to that particular device.

Related

How to restrict calls to api rest

Firstly, sorry for the format of this question. I know the rules for this site, but I haven't previous work nor investigation, because, basically, I don't know where to start...
I'm content with a tip for I start.
I'm searching how restrict calls to an api rest made in expressjs from (only) a native mobile app (ios and android). I thinking in a token, but I don't think it's a very safe idea, because any people can take the token and simulate to be the mobile app, or I'm wrong?
Thanks in advance!
You cannot restrict access to a REST api from only a native mobile app. The internet is wide open for access from any client so if you have a REST server, then any client can access it, whether mobile or not.
You can control access via authentication. So, usually what one would do is to require some sort of account access and then have your server watch for unexpected or unauthorized use and, if found, you disable that account.
You could also embed "secret" credentials in your mobile app and use those as the authorization over SSL, but a determined hacker could still get the credentials out of your app if they wanted to.
You can't restrict a public REST Api. Any request that your mobile users send can also be send by anyone.
Maybe you can keep a 'secret' string and attcah to http requests, but it can be easily exposed by sniffing http traffic or decompiling the apk.
Your last option is restricting access by IP, but I don't know if it's suitable with your case.
Of cource any one can simulate any APIs, it would just need a sniffer and the understanding of the right data format (like the format of the JSON object that is sent by your client app).
Anyone can go ahead, figure out how the WhatsApp works and simulate such an app. This can even happen when you are getting each user to Sign up first, then the "simulator" will just have to simulate that process too.
But, generally, what a developer wants is that :
People use his app
People use his REST APIs
Point 1 implies Point 2, but Point 2 does not imply Point 1. You cannot stop a hacker or someone from using your APIs without your App, you can just slow his simulator-development-process using some techniques.
Then you might ask, cant he flood your server with millions of request ? Of course he can. That a DoS attack. In theory, he can even use manny android simulators and install your App and then flood your server with millions of request.
Any one can use your APIs if you open it to the internet world.

Is it safe to store a JWT in localStorage with ReactJS?

I'm currently building a single page application using ReactJS.
I read that one of the reasons for not using localStorage is because of XSS vulnerabilities.
Since React escapes all user input, would it now be safe to use localStorage?
In most of the modern single page applications, we indeed have to store the token somewhere on the client side (most common use case - to keep the user logged in after a page refresh).
There are a total of 2 options available: Web Storage (session storage, local storage) and a client side cookie. Both options are widely used, but this doesn't mean they are very secure.
Tom Abbott summarizes well the JWT sessionStorage and localStorage security:
Web Storage (localStorage/sessionStorage) is accessible through JavaScript on the same domain. This means that any JavaScript running on your site will have access to web storage, and because of this can be vulnerable to cross-site scripting (XSS) attacks. XSS, in a nutshell, is a type of vulnerability where an attacker can inject JavaScript that will run on your page. Basic XSS attacks attempt to inject JavaScript through form inputs, where the attacker puts <script>alert('You are Hacked');</script> into a form to see if it is run by the browser and can be viewed by other users.
To prevent XSS, the common response is to escape and encode all untrusted data. React (mostly) does that for you! Here's a great discussion about how much XSS vulnerability protection is React responsible for.
But that doesn't cover all possible vulnerabilities! Another potential threat is the usage of JavaScript hosted on CDNs or outside infrastructure.
Here's Tom again:
Modern web apps include 3rd party JavaScript libraries for A/B testing, funnel/market analysis, and ads. We use package managers like Bower to import other peoples’ code into our apps.
What if only one of the scripts you use is compromised? Malicious JavaScript can be embedded on the page, and Web Storage is compromised. These types of XSS attacks can get everyone’s Web Storage that visits your site, without their knowledge. This is probably why a bunch of organizations advise not to store anything of value or trust any information in web storage. This includes session identifiers and tokens.
Therefore, my conclusion is that as a storage mechanism, Web Storage does not enforce any secure standards during transfer. Whoever reads Web Storage and uses it must do their due diligence to ensure they always send the JWT over HTTPS and never HTTP.
Basically it's OK to store your JWT in your localStorage.
And I think this is a good way.
If we are talking about XSS, XSS using CDN, it's also a potential risk of getting your client's login/pass as well. Storing data in local storage will prevent CSRF attacks at least.
You need to be aware of both and choose what you want. Both attacks it's not all you are need to be aware of, just remember: YOUR ENTIRE APP IS ONLY AS SECURE AS THE LEAST SECURE POINT OF YOUR APP.
Once again storing is OK, be vulnerable to XSS, CSRF,... isn't
I know this is an old question but according what #mikejones1477 said, modern front end libraries and frameworks escape the text giving you protection against XSS. The reason why cookies are not a secure method using credentials is that cookies doesn't prevent CSRF when localStorage does (also remember that cookies are accessible by JavaScript too, so XSS isn't the big problem here), this answer resume why.
The reason storing an authentication token in local storage and manually adding it to each request protects against CSRF is that key word: manual. Since the browser is not automatically sending that auth token, if I visit evil.example and it manages to send a POST http://example.com/delete-my-account, it will not be able to send my authn token, so the request is ignored.
Of course httpOnly is the holy grail but you can't access from reactjs or any js framework beside you still have CSRF vulnerability. My recommendation would be localstorage or if you want to use cookies make sure implemeting some solution to your CSRF problem like Django does.
Regarding with the CDN's make sure you're not using some weird CDN, for example CDN like Google or bootstrap provide, are maintained by the community and doesn't contain malicious code, if you are not sure, you're free to review.
A way to look at this is to consider the level of risk or harm.
Are you building an app with no users, POC/MVP? Are you a startup who needs to get to market and test your app quickly? If yes, I would probably just implement the simplest solution and maintain focus on finding product-market-fit. Use localStorage as its often easier to implement.
Are you building a v2 of an app with many daily active users or an app that people/businesses are heavily dependent on. Would getting hacked mean little or no room for recovery? If so, I would take a long hard look at your dependencies and consider storing token information in an http-only cookie.
Using both localStorage and cookie/session storage have their own pros and cons.
As stated by first answer: If your application has an XSS vulnerability, neither will protect your user. Since most modern applications have a dozen or more different dependencies, it becomes increasingly difficult to guarantee that one of your application's dependencies is not XSS vulnerable.
If your application does have an XSS vulnerability and a hacker has been able to exploit it, the hacker will be able to perform actions on behalf of your user. The hacker can perform GET/POST requests by retrieving token from localStorage or can perform POST requests if token is stored in a http-only cookie.
The only down-side of the storing your token in local storage is the hacker will be able to read your token.
One thing to keep in mind is whether the JWTs are:
First party (ie. simply for accessing your own server commands)
Third party (ie. a JWT for Google, Facebook, Twitter, etc.)
If the JWT is first-party:
Then it doesn't matter that much whether you store the JWT in local storage, or a secured cookie (ie. HttpOnly, SameSite=strict, and secure) [assuming your site is already using HTTPS, which it should].
This is because, assuming an XSS attack succeeds (ie. an attacker was able to insert Javascript code through a JS dependency that is now running on all visitor browsers), it's "game over" anyway; all the commands which were meant to be secured by the "JWT token verifications", can now be executed by the attacker just by having the script they've inserted into the frontend JS call all the needed endpoints. Even though they can't read the JWT token itself (because of the cookie's http-only flag), it doesn't matter because they can just send all the needed commands, and the browser will happily send the JWT token along with those commands.
Now while the XSS-attack situation is arguably "game over" either way (whether local-storage or secured cookie), cookies are still a little better, because the attacker is only able to execute the attacks if/when the user has the website open in their browser.
This causes the following "annoyances" for the attacker:
"My XSS injection worked! Okay, time to collect private data on my boss and use it as blackmail. Dang it! He only ever logs in while I'm here at work. I'll have to prepare all my code ahead of time, and have it run within the three minutes he's on there, rather than getting to poke around into his data on the platform in a more gradual/exploratory way."
"My XSS injection worked! Now I can change the code to send all Bitcoin transfers to me instead! I don't have any particular target in mind, so I don't need to wait for anyone. Man though, I wish I could access the JWT token itself -- that way I could silently collect them all, then empty everyone's wallets all at once. With these cookie-protected JWTs, I may only be able to hijack a few dozen visitors before the devs find out and suspend transfers..."
"My XSS injection worked! This'll give me access to even the data that only the admins can see. Hmmm, unfortunately I have to do everything through the user's browser. I'm not sure there's a realistic way for me to download those 3gb files using this; I start the download, but there are memory issues, and the user always closes the site before it's done! Also, I'm concerned that client-side retransfers of this size might get detected by someone."
If the JWT is third-party:
In this case, it really depends on what the third-party JWTs allow the holder to do.
If all they do is let someone "access basic profile information" on each user, then it's not that bad if attackers can access it; some emails may leak, but the attacker could probably get that anyway by navigating to the user's "account page" where that data is shown in the UI. (having the JWT token just lets them avoid the "annoyances" listed in the previous section)
If, instead, the third-party JWTs let you do more substantial things -- such as have full access to their cloud-storage data, send out messages on third-party platforms, read private messages on third-party platforms, etc, then having access to the JWTs is indeed substantially worse than just being able to "send authenticated commands".
This is because, when the attacker can't access the actual JWT, they have to route all commands through your 1st-party server. This has the following advantages:
Limited commands: Because all the commands are going through your server, attackers can only execute the subset of commands that your server was built to handle. For example, if your server only ever reads/writes from a specific folder in a user's cloud storage, then the attacker has the same limitation.
Easier detection: Because all the commands are going through your server, you may be able to notice (through logs, sudden uptick in commands, etc.) that someone has developed an XSS attack. This lets you potentially patch it more quickly. (if they had the JWTs themselves, they could silently be making calls to the 3rd-party platforms, without having to contact your servers at all)
More ways to identify the attacker: Because the commands are going through your server, you know exactly when the commands are being made, and what ip-address is being used to make them. In some cases, this could help you identify who is doing the attacks. The ip-address is the most obvious way, though admittedly most attackers capable of XSS attacks would be aware enough to use a proxy.
A more advanced identification approach might be to, say, have a special message pop up that is unique for each user (or, at least, split into buckets), of such a nature that the attacker (when he loads up the website from his own account) will see that message, and try to run a new command based on it. For example, you could link to a "fake developer blog post" talking about some "new API" you're introducing, which allows users to access even more of their private data; the sneaky part is that the URL for that "new API" is different per user viewing the blog post, such that when the API is attempted to be used (against the victim), you know exactly who did it. Of course, this relies on the idea that the attacker has a "real account" on the site alongside the victim, and could be tempted/fooled by this sort of approach (eg. it won't work if the attacker knows you're onto him), but it's an example of things you can do when you can intercept all authenticated commands.
More flexible controlling: Lets say that you've just discovered that someone deployed an XSS attack on your site.
If the attackers have the 3rd-party JWTs themselves, your options are limited: you have to globally disable/reset your OAuth/JWT configuration for all 3rd-party platforms. This causes serious disruption while you try to figure out the source of the XSS attack, as no one is able to access anything from those 3rd-party platforms. (including your own server, since the JWT tokens it may have stored are now invalid)
If the JWT tokens are instead protected in http-only cookies, you have more options: You can simply modify your server to "filter out" any reads/writes that are potentially dangerous. In some cases added this "filtering" is a quick and easy process, allowing your site to continue in "read-only"/"limited" mode without disrupting everything; in other cases, things may be complex enough that it's not worth trusting the filter code for security. The point though is that you have more options.
For example, maybe you don't know for sure that someone has deployed an XSS attack, but you suspect it. In this case, you may not want to invalidate the JWT tokens of every user (including those your server is using in the background) simply on the suspicion of an XSS attack (it depends on your suspicion level). Instead, you can just "make things read-only for a while" while you look into the issue more closely. If it turns out nothing is wrong, you can just flip a switch and re-enable writes, without everyone having to log back in and such.
Anyway, because of these four benefits, I've decided to always store third-party JWTs in "secured cookies" rather than local storage. While currently the third-party JWTs have very limited scopes (such that it's not so big a deal if they are stolen), it's good future-proofing to do this, in case I'd like my app to request access to more privileged functionalities in the future (eg. access to the user's cloud storage).
Note: The four benefits above (for storing third-party JWTs in secured cookies) may also partially apply for first-party JWTs, if the JWTs are used as authentication by multiple backend services, and the domains/ip-addresses of these other servers/services are public knowledge. In this case, they are "equivalent to third-party platforms", in the sense that "http-only cookies" restrict the XSS attacker from sending direct commands to those other servers, bringing part of the benefits of the four points above. (it's not exactly the same, since you do at least control those other servers, so you can activate read-only mode for them and such -- but it'll still generally be more work than making those changes in just one place)
I’m disturbed by all the answers that suggest not to store in local storage as this is susceptible to an XSS attack or a malicious library. Some of these even go into long-winded discussions, even though the answer is pretty small/straightforward, which I’ll get to shortly.
Suggesting that is the equivalent of saying “Don’t use a frying pan to cook your food because if you end up drunk one night and decide to fry, you’ll end up burning yourself and your house”.
If the jwt gets leaked due to an XSS attack or malicious library, then the site owner has a bigger problem: their site is susceptible to XSS attacks or is using a malicious library.
The answer: if you’re confident your site doesn’t have those vulnerabilities, go for it.
Ref: https://auth0.com/docs/security/data-security/token-storage#browser-local-storage-scenarios
It is not safe if you use CDN's:
Malicious JavaScript can be embedded on the page, and Web Storage is compromised. These types of XSS attacks can get everyone’s Web Storage that visits your site, without their knowledge. This is probably why a bunch of organizations advise not to store anything of value or trust any information in web storage. This includes session identifiers and tokens.
via stormpath
Any script you require from the outside could potentially be compromised and could grab any JWTS from your client's storage and send personal data back to the attacker's server.
Localstorage is designed to be accessible by javascript, so it doesn't provide any XSS protection. As mentioned in other answers, there is a bunch of possible ways to do an XSS attack, from which localstorage is not protected by default.
However, cookies have security flags which protect from XSS and CSRF attacks. HttpOnly flag prevents client side javascript from accessing the cookie, Secure flag only allows the browser to transfer the cookie through ssl, and SameSite flag ensures that the cookie is sent only to the origin. Although I just checked and SameSite is currently supported only in Opera and Chrome, so to protect from CSRF it's better to use other strategies. For example, sending an encrypted token in another cookie with some public user data.
So cookies are a more secure choice for storing authentication data.
Isn't neither localStorage or httpOnly cookie acceptable? In regards to a compromised 3rd party library, the only solution I know of that will reduce / prevent sensitive information from being stolen would be enforced Subresource Integrity.
Subresource Integrity (SRI) is a security feature that enables
browsers to verify that resources they fetch (for example, from a CDN)
are delivered without unexpected manipulation. It works by allowing
you to provide a cryptographic hash that a fetched resource must
match.
As long as the compromised 3rd party library is active on your website, a keylogger can start collecting info like username, password, and whatever else you input into the site.
An httpOnly cookie will prevent access from another computer but will do nothing to prevent the hacker from manipulating the user's computer.
There's a useful article written by Dr. Philippe De Ryck which gives an insight into the true impact of vulnerabilities particularly XSS.
This article is an eye opener!
In a nutshell, primary concern of the developer should be to protect the web application against XSS and shouldn't worry too much about what type of storage area is used.
Dr. Phillipe recommends the following 3 steps:
Don't worry too much about the storage area. Saving an access token in localStorage area will save the developer a massive amount of time for development of next phases of the application.
Review your app for XSS vulnerabilities. Perform a through code review and learn how to avoid XSS within the scope of your templating framework.
Build a defense-in-depth mechanism against XSS. Learn how you could further lock down your application. E.g. utilising Content Security Policy (CSP) and HTML5 sandboxing.
Remember that once you're vulnerable to XSS then its game over!
TLDR;
Both work, but using a cookie with httpOnly is way safer than using localStorage, as any malicious javascript code introduced by XSS can read localstorage.
I'm coming late to the discussion, but with the advantage of more mature and modern auth protocols like OpenID Connect.
TL;DR: The preferred method is to store your JWT Token in memory: not in a cookie, and not in localstorage.
Details
You want to decouple the responsibility of authenticating users from the rest of the work your app does. Auth is hard to get right, and the handful of teams that spend all their time thinking about this stuff can worry about the details you and I will never get right.
Establish a dedicated Identity Provider for your app, and use the OpenID Connect protocol to authenticate with it. This could be a provider like Google, Microsoft, or Okta, or it could be a lightweight Identity Server that federates to one or more of those other services.
Use the Authorization Code Flow to let the user authenticate and get the access token to your app. Use a respected client library to handle the OpenID Connect details, so you can just have the library notify your app when it has a valid token, when a new valid token has been obtained via refresh, or when the token cannot be refreshed (so the user needs to authenticate again). The library should be configured (probably by default) to avoid storing the token at all.
FAQ
What happens when someone refreshes the page? I don't want to make them log in again.
When the app first loads, it should always redirect the user to your Identity Provider. Based on how that identity provider handles things, there's a good chance the user won't have to log in. For example, if you're federating to an identity provider like Google or Microsoft, the user may have selected an option indicating that they are on a trusted device and they want to be remembered. If so, they won't need to log in again for a very long time, long after your auth token would have expired. This is much more convenient for your users.
Then again, if the user indicated they're on a shared device and shouldn't automatically be logged in in the future, you want to force another login: you cannot differentiate between someone who refreshed their browser window and someone who reopened a closed browser and navigated to a page stored in the browser's history.
Isn't the Identity Provider using cookies to keep the user logged in? What about CSRF or XSS attacks there?
Those implementation details are specific to the Identity Provider. If they're using cookies, it's their job to implement Anti-CSRF measures. They are far less likely than you are to use problematic third-party libraries, or import compromised external components, because their app only has one job.
Shouldn't I spend my time addressing XSS attacks instead? Isn't it "game over" if someone injects code into my app?
If it's an either/or proposition, and you have reason to believe your app has XSS or Code Injection vulnerabilities, then those should definitely take precedence. But good security involves following best-practices at multiple levels, for a kind of layered security.
Plus, using a trusted third-party library to connect to trusted third-party security providers should hopefully save you time that you would have spent dealing with a variety of other security-related issues.
It is safe to store your token in localStorage as long as you encrypt it. Below is a compressed code snippet showing one of many ways you can do it.
import SimpleCrypto from 'simple-crypto-js';
const saveToken = (token = '') => {
const encryptInit = new SimpleCrypto('PRIVATE_KEY_STORED_IN_ENV_FILE');
const encryptedToken = encryptInit.encrypt(token);
localStorage.setItem('token', encryptedToken);
}
Then, before using your token decrypt it using PRIVATE_KEY_STORED_IN_ENV_FILE

How to store credentials in an Outlook Add-in

I'm looking for the correct, secure way to store credentials for a third party API in an Outlook add-in. This overview of the different storage options only says not to store credentials in Settings, but not where to put them, so I assumed the RoamingSettings would be okay. Then I ran into this page with information about RoamingSettings, where it says that is not the right location either.
The question then becomes: What is the right place? Should I build my own storage solution and store/encrypt the credentials in a file or cookie? That does not feel very secure either, since we are talking about what is basically a web app running in an Iframe.
I assume you cannot implement another authorization scheme (token based, cookies etc.) for your API and you are stuck with Basic Authentication and its issues. If you are using ASP.NET, with all the samples available it could be very easy to add another authentication scheme that is more adapted to web clients (such as Office web add-ins).
Having said that, for me your best option is to use HTML5 storage or cookie storage (if not implemented by browser) to store your credentials.
The fact that the app is iFramed is not really a big deal. Those storages (HTML5: sessionStorage/localStorage) rely on domains separation which means that the storage slots where you will put the credentials will not be be visible by other apps, even those living on the parent iFrame.
You may also consider the fact that you may serve the web add-ins and the apis from the same domain. They are both web applications!
You can do what Outlook itself does for its POP3/SMTP/IMAP4 passwords - use CredRead / CredWrite Windows API functions. The data can only be decrypted under the local Windows account used to encrypt the data, so it cannot be take to a different machine and decrypted.
I don't think you can access these functions from JavaScript. This is for an OWA addin, not the Outlook application, is it?

Reading data from a security token in a browser

I would like to write a JS function to have access from the browser to the public data stored on the hardware security token inserted in an USB port.
Specifically, in an intranet where ALL users have security tokens, I would like to have some sort of landing page, which will ask the user to enter his/her security token credentials (inserted in the USB port), and then read the public information from that token (I do not really need ALL of them, but I am interested mostly in the user name, certificate name(s) loaded in the token and their expiration date) and load them in the web page (to be displayed).
I have little to none experience with security devices like that, but I assume this is not a very complicated issue (though "googling" did not manage to get me in the right direction of how to make it work).
Thank you.
In my company we created a service installed installed in client's device, this service uses java to access the token and it provides an API(in client localhost), not sure if it's the best way but it works, if you find another way to solve this issue please leave a comment.
You can use the WinUSB API implemented in Chrome v54+.
You'll need to know the intrinsic structure of your USB token.

How it is possible to not expose you secret key with a Javascript OAuth library?

Looking at Twitter OAuth Libraries, I saw this note:
Be cautious when using JavaScript with OAuth. Don't expose your keys.
Then, looking at jsOAuth examples, I noticed that the keys are exposed in the code.
So my question is: How it is possible to not expose your keys when you use an OAuth library in Javascript?
Thanks.
UPDATE: Ok, maybe jsOAuth is not the right library to use, but how it is possible to do authentication with OAuth on a full Javascript web site?
As said in the documentation linked by you:
Written in JavaScript, jsOAuth aims to be a fully featured open source OAuth library for use in Adobe AIR, Appcelerator Titanium and PhoneGAP. In fact, anywhere that javascript can be used and has cross-domain XMLHttpRequests. For security reasons jsOAuth doesn't run in the browser. Browsers are only mentioned here for running the test suite. If you need jsOAuth in the browser, write an extension.
A good answer to your added question is available here:
Secure OAuth in Javascript
The only really reasonable way, right now, to do OAuth 1 in the browser, is to route API-calls via your server.
There simply is no way, as far as I have understood it, around this. If you do OAuth 1.0a calls through JavaScript from the browser -> You will HAVE to expose your consumer secret and access token secret, to at least the end user.
You cannot store these credentials in:
a cookie, the user can find them.
local storage, the user can find them (better than cookie though, since it does not entail sending a cookie back and forth all the time over HTTP)
in javascript, the user can find them (although this is probably your best bet since it is easier to obscure).
If it were only the access token secret that was exposed to the end user, that would be bearable - since it is in fact he/she who have authenticated your application. But losing your consumer secret is really not so hot, it means that your application is eligible for identity theft. I.e someone else could write an app that claims to be your app.
Even if you made it work securely in the browser, you are hampered by cross domain security blocks.
You could also make a script that sends all necessary values and parameters to the server to do the signing with.
The signed URL can then be sent back to the client (browser) that in turn does the actual request.
I have implemented OAuth 1.0a on the Twitter API that way using jsonp requests.
The benefit of this is that the response body is not relayed via your server, saving bandwidth.
That way you can have your cookie and eat it too.

Categories