React authentication using localStorage - javascript

I am trying to figure out how to build a basic login/signup feature for my React application. So I am considering creating a HoC/parent class that does things such as logging in and checking if a user logged in.
SO now I have come to you to figure out the best way to store whether a user is logged in or not. What I saw is using localStorage. But that could be accessed by anyone really right so I can just store a flag saying isLoggedIn or something? Would I have to encrypt some token such as a username.password and then on every page load do a call to the DB? That seems a little much. Or have a missunderstood something?

You can use JSON Web Tokens (JWT).
When the user logs in, call say /login of your backend to check the password against your database. If successful, issue a JWT containing the username and its role, for instance (not the password).
You can always tell then if the user is logged in by verifying directly with Javascript the cryptographic signature of the token (if the readable content, such as the user name, has been altered, then the signature will not match anymore). This way you don't need to interrogate the database until the token expires.
What I saw is using localStorage. But that could be accessed by anyone really right
No. It also has the advantage over cookies that it is accessible only from the same domain. In principle there is a way that your token gets stolen (e.g. XSS attacks, or copied from dev tools on your laptop when you are away), but the expiration time that you will add to it will make it valid for only a few hours.

Related

Would the following JWT refresh token flow be considered secure?

I am creating a web server for a site with authentication using JWTs. Since this is going to be a publicly available system once ready, I would like to know if the following authentication flow using JWT access and refresh tokens could be considered secure.
In this case it is assumed that one server serves both the auth API and resources
When the server starts, it will generate a "run ID" which is the current UNIX timestamp and random characters/UUID. This is stored in memory and any restart will generate a new one.
The user obtains an initial HttpOnly access and refresh tokens when logging in or registering. Access token has a short lifespan (~5 mins.) and refresh token has a longer lifespan (~2 hours).
The access token functions like normal and contains the userID.
The refresh token has the userID, the server's run ID and its own unique "token ID" (similar to run ID, unique for each refresh token)
Instead of the user calling a token refresh endpoint, new access and refresh tokens are made when calling an endpoint that requires authorisation if the following criteria are met:
The access token has expired
The refresh token has not expired
The run ID in the refresh token matches up with the current run ID
The refresh token's token ID isn't blacklisted
In the event that there is a run ID mismatch or the token ID has been put on a blackist, the refresh token is instantly considered invalid.
The token ID blacklist is stored in memory (like the run ID) as an array with the ID and expiration time.
This allows a user to logout and blacklist that specific refresh token from being used.
This also allows any system administrators to emergency invalidate all refresh tokens by restarting the server since the runID will change.
I would like to know if this can be considered a secure authentication flow
It took me a while to understand what is going on with the tokens and your motivation around it. I believe what you did here is more complicated than reality requires and there should be little reason to introduce this level of complexity. Please also note, that security in its definition is a double edged sword. It's an eternal conflict between integrity and confidentiality VS availability. If for some reason we screw the systems availability then it will not be considered secure in the same sense, that turning a computer off is not considered a solution of security issues.
Having said that, let's look into your solution.
You intend to use access and refresh JWT tokens. How should a logout in such system look like? Well, you simply forget the token information on the client side or in case you want to hold tokens in cookies - which I believe you want to have based on "HttpOnly" flag - you can clean up the cookies. This is it. Once the information is gone from the client, the tokens can not be easily recreated. There is no need to blacklist the tokens on the server. It is in clients best interest to 'forget' the tokens he is not using and once the token is gone, there is no second copy to replace it.
We use token blacklisting in case we want to deal with a scenario like real-time user account locking. An expensive thing to implement if you ask me.
You can still try to blacklist refresh tokens, but assuming your authentication mechanism has access to the user pool, it can simply check in the database if the user is locked, no need to cache anything here.
Next thing I notice is that what you did here reassembles strongly simple Http Session handling including loosing the session once the server restarts. Why not forget the tokens and use a simple session instead?
I also wonder, why you intend to have only one instance of your system. In the High Availability age and playing with JWT tokens it would totally make sense to separate authentication module from logic and have more than one instance of both.
Please also note, that no one will be able to tell you, whether what you do is secure, until they can look into your code, configuration and ideally - working system. There are many small pieces that can break the solution. Ideally have a look into the OWASP ASVS (Application Security Verification Standard) available here to see, how deep the rabbit hole goes.

Encrypting, then storing access token in localStorage

My API returns an access token after a user signs in.
All future requests must include this token in the Authentication header.
I'd like users to remain logged in even if they close and re-open the browser.
Can I safely store an encrypted version of this access token in localStorage, retrieve it, unencrypt it in my React client code and send it off to the API?
Sure, you could use something like this https://www.npmjs.com/package/aes-js or another library if you like at https://www.npmjs.com/search?q=keywords:encrypt.
I think the real question is why? The user can always see the unencrypted value in the network request of the dev tools. If the access token is tied to a username and password that the user owns why can't they see it? It's really just another way to write their username and password. If it is associated with an username that belongs to your app (such as your server uses that username to login to another server for all requests, not just for this one user) then you shouldn't pass it to the browser ever because it is easy to steal.

Securing API calls without token

I'm building an app and an API endpoint using PHP(I know what you thinking!). My issue is that if I ask user for username and password on opening the app for the first time, since I can't store these details locally because they could be compromised. I'd send these through Post request to server then generate a token depending on whether the user is the right one. After getting response I must store this token locally right?
Yes!. there's expiration for the token. After the token is expired, I don't want to ask user for their name and password but want to access API still authenticating as that user. How will I do this?
If I use Oauth it's still the same procedure right? I should store something locally. won't that be compromised? I'm very confused.
How does other apps work. I'm sure they doing something in the background. They ask us for credentials only once and all subsequent API calls will be secured. Won't the token expire in that case or what?
Can i secure API calls without storing anything locally? I don't want API to be accessed from anywhere else but app.
Use android SharedPreferences. It should be very secure unless you deliberately expose it e.g. its accessible via an exported content provider missing the (android:exported="false") in the manifest. You can also use sqlite but there is no point of using a db table for one or two rows of data.You can also encrypt the user name and password to add one more security layer to protect rooted users.
Furthermore to protect the data in the network you should use ssl in the backend so no one can sniff the credentials.

Improving security with JS

I’m trying some little ideas, and I’ve hit a snag.
At the moment, when a user logs in, their password is stored in a variable which is handled later. Obviously all one has to do to get hold of the password is to go into the developer tools or console or whatever and add a statement like alert(pass.value);.
I know this is unrealistic but its been bugging me. Is there any way of detecting an alert statement and scrambling the password somehow? A regex or string replace?
Thanks!
If you want to have a secure system, don't store the password on the client side. There is absolutely nothing you can do in JavaScript that will prevent somebody from accessing the password if it is stored in a JavaScript variable.
All of your authentication should be handled on the server side. If you are storing passwords somewhere, do not store them in plain text, and do not use a home-brew encryption method. Cryptology is full of minefields and it's very easy to get something wrong, and I would recommend using a well thought-out system like bcrypt.
I would advise against keeping any kind of credential information client-side. One viable solution that's easy to implement is is a security token password. A simple process would look like this:
User access website. Informs credentials.
Website validates credentials. Creates temporary token associated with user ID, stores it client-side.
User access website. Informs token.
Token is validated against storage, user identified.

securely store user password locally in a jquery mobile app

I need to access an api which requires http authentification on a per user basis using a jquery mobile api.
I plan to make the app available as a website as well as packaging it in Cordova for various devices.
If I have a login form which captures the username and password and store this as a javascript variable, is there any way this data could be exposed?
If so, what's the best alternative to handle storing the users authentification details? I am reticent to build an intermediary server if I don't have to.
Many Thanks. :D
I would suggest not storing the username or password in the localStorage, but instead to store an access token. Access tokens can be updated and changed frequently, it also doesn't reveal who the user is or what their hashed password is.
Besides iOS Keychain or if you're coding it for a non-iPhone device for added security you can:
Change the access token at each login and each time the app is used
Store the device ID in the server database (see http://docs.phonegap.com/en/2.2.0/cordova_device_device.md.html#device.uuid)
Clear the localStorage and request a new login if the access token or device ID doesn't match the data stored in the database
Make sure you don't store the device ID in the localStorage.
For added security you can also store the user's IP address in the database and check (server side) if the IP address matches, but this might too much since the user would have to login every time they connect to the internet in a new location or if their IP address changes.
Storing the IP address in the server database then checking if it matches (server side) would probably be the safest since it wouldn't matter if someone got hold of the localStorage data.
So I understand you don't control the backend you log in to? If you do, I would be more inclined to send username/password once, and then store some access token that will allow you subsequent access.
If you don't control the backend, you're stuck with storing username/password. I would say, setting them in localStorage is as safe as it gets (which is, admittedly, not very safe. Then again, if your login doesn't happen on HTTPS, I would be more worried about passwords leaking there than from the device itself). You could make the passwords harder to find, not call the variables "username/password", encrypt them in javascript, obfuscate your code. But in the end, they can always be retrieved without too much effort with the right access to the device.
After packaging as native app, you have more options, e.g. iOS keychain: http://shazronatadobe.wordpress.com/2010/11/06/ios-keychain-plugin-for-phonegap/

Categories