Store secret key in react securely after creating secure channel - reactjs

My question is -> where can I secure one secret key in the frontend.
The context is, the server is using RSA to create a public and private key, the client will do the same.
They will negotiate a secret key for AES encryption, for example, therefore creating a supposedly secure channel.
So now backend stores the secret key they agreed, which is alright because no one can access it (normally), and frontend as to store it too, otherwise it can't encrypt or decrypt the information received or sent to the backend.
So now the problem is:
react app are not secure to have secrets stored, and even if I store the key in a variable people can access it if they use dev tools right?
So how can someone create a secure channel with the frontend, if my key is never safe?
Am I missing something?

Disclaimer: I am not a front-end expert, I would make a comment but have not enough reputation :P
I will take as an example telegram app.
Telegram does not support E2E chats on web browsers. And the reason of that I guess is because the best practice to store a shared key is on RAM and for long-term on your local storage (hard disk) and not in plaintext.
If you want to save a shared key on browser, I guess the only way to do so, is on local storage (as like our cookies are stored) or I guess most secure using redux like solutions (Redux State is stored in Primary Memory (or) Secondary Memory?).
Now let's go on the encryption protocol part...
I don't know if this is just a mini project, but if you want to make it right, you should dig more to the encryption, authorization and verification process.
So I suggest you to check about MTProto: https://core.telegram.org/mtproto
And here they describe the E2E preparation (If you need to use somewhere hashing, do NOT go below sha256): https://core.telegram.org/api/end-to-end
I hope my answer helped you even a bit.

Related

Is there a secure way to store data like login credentials on client-side?

I am using React JS, and I would like to store user's login credentials on client's browser so they don't have to enter email and password each time.
How can I securely store user's login credentials in the browser?
Define securely. If your definition is like "no one beside the user can use the credentials to access the application" then forget it. No technical or technological mean can make it happen. The definition is simply to broad, and if the attack models include the attacker having access to your user agent (browser) or physical access to your device, then the solution gets hopeless pretty quick.
Think encryption can help? You have encrypted the payload using some key. Now you have to protect the key. Encryption does not solve your problem. It just shifts it somewhere else. All security through obscurity solutions use stuff like this.
We usually define security of passing secrets as something that requires us to be protected from the remote attacker. Someone who has the access to the wire and can sniff the traffic, someone who may have access to some of the remote machines you are communicating with. This makes the problem solvable at least to some degree. It allows you to use either well configured cookies or local web storage to use it as cache.
Having said that - storing credentials is usually considered bad practice anyway. You may store your refresh tokens, you may store your session id, but you should not store your users credentials in anything else but a password manager. Refresh tokens and session ids will expire on its own and does not reveal anything about the user when they do.
To better understand what is allowed and disallowed when designing your solution please have a look into OWASP ASVS.
Even if there are many replies on the same subject for numerous queries, I wanted to share my ideas nonetheless.
It is impossible to completely safeguard data saved on local storage and it is a bad practice to save user credentials on localStorage , as #Marek pointed out in the prior response, but we can make it difficult for people to crack it.
Encryption is one of the solutions in this case, but it is still insufficient to secure local storage if you just encrypt the data and store it there using a shared or application-specific encryption key.
Here is why.
Consider the following scenario: you’ve encrypted the user’s login information and saved it locally. When you reload the platform, you’re decrypting the data that’s been written to local storage and marking the user as logged in or logged out. Your website and the platform use a single secure key to encrypt and decrypt, which means only your website knows how to decrypt.
If someone copies data from local storage and pastes it into a separate browser, then visits your site, your website will authenticate the user. Why?
because your website understands how to decode data!
then, what can we do?
It is preferable to generate a special encryption key that is only known by each browser and use that key to encrypt the data.
One method is to utilise the react-secure-storage package, which generates a special encryption key known only to the browser being used.
Here is how to use it:
yarn add react-secure-storage
npm install react-secure-storage
Sample code
import { useEffect } from "react";
import secureLocalStorage from "react-secure-storage";
const App = () => {
useEffect(() => {
secureLocalStorage.setItem("object", {
message: "This is testing of local storage",
});
secureLocalStorage.setItem("number", 12);
secureLocalStorage.setItem("string", "12");
secureLocalStorage.setItem("boolean", true);
let value = secureLocalStorage.getItem("boolean");
}, []);
return (
<div>
This is a sample code
</div>
);
}
export default App;

Ways of handling API KEYs in React?

Read thru a lot of posts and articles on how people handle api keys. I think some made it secure to get api keys via Node Server, some store it at .env file.
Sample posts I've read
https://www.rockyourcode.com/secret-keys-in-react/
https://github.com/react-boilerplate/react-boilerplate/issues/1744#issuecomment-303112505
My situation:
Currently I'm storing my API KEYs in .env files, because I'm uglifying my code in React. Those files are unreadable even via Inspect Element, but now all my api keys are exposed in readable format.
My use case:
My website don't require sign in, hence no authentication needed. Basically it's API KEY for firebase analytics. I don't think it make sense to create a Node Server to get the api key here? (And again, I don't need authentication)
How can I better handle the API KEYs?
I don't think exposing the Firebase key is a security threat as per this article: https://medium.com/#paulbreslin/is-it-safe-to-expose-your-firebase-api-key-to-the-public-7e5bd01e637b
GCP usually allows you to restrict api keys by domain. That maybe one way to secure your config and prevent other people from spoofing requests as your project.
In any other situation however, I would not expose api keys in client-side code and have an intermediate server or a cloud-function that uses it instead.

Secure / Authenticated interaction from a WP7 app

I am working on a WP7 application. This WP7 application will interact with some web services that I have created. I do not want other applications interacting with these web services. The reason why is because I do not want them stealing my data. With that in mind, here is what I'm currently doing:
Connecting to web services via HTTPS
Making my users initially login to the application
Passing the users username / password with each web service interaction
At this time, I don't see what is stopping a malicious developer from creating a username / password combo and using that account in their application to interact with my web services. How do I really lock this thing down?
Thanks!
As a start towards a more secure system you should stop storing the password and sending it over the wire with each request (even if you're using SSL).
If you must pass it with each request, store a salted hash of the password and use that instead.
I'm using a multi layered approach to this problem. I recommend thinking creatively and using a variety of methods to validate that requests are coming from devices you expect requests to come from.
Alternatively, if there is any merit in your scenario, open up your api to 3rd party developers and make this work toward your objectives.
If you do decide to store a key in your app, don't store RAW text but instead declare a byte array of the UTF8 values, this won't be as easy to read.
You can then handshake with your service using a salted hash of the key the first time the app is run, the service hands out another key for the device to actually use day-to-day.
The phone should have an almost accurate time, so you can recalculate the key each day or hour. You can also revoke the key at the server end for just that device.
This API will be useful in ensuring you can blacklist a device permanently.
DeviceExtendedProperties.GetValue(“DeviceUniqueId”).ToByte();
I've not looked into symmetric encryption by you might even be able to use the above unique ID as a private key.
I think the key to success is that first hand-shake, and ensuring that is not snooped. If it's a really important system, then don't use any of these ideas since rolling your own encryption is always flimsy to anyone with serious intent - use well-known methods and read up.
Luke
You could introduce an "Authorized Application ID" feature where the application sends its name or identifier within each HTTP request body. Then on the server side you can verify the application's identity (e.g. store the authorized app ID's in a table). The application ID would be encrypted within the HTTP(S) body.
This would also give you the option of pushing out new application ID's in updated versions of the WP7 application if you wanted to get rid of an older application ID. You'd also be able support new applications on difference devices or platforms in the future.
You may want to look at this
http://channel9.msdn.com/Blogs/Jafa/Windows-Phone-7-Trade-Me-Developer-Starter-Kit

Google apps applications talk to each other

I am looking for a way for two Google Apps applications to talk to each other and share data between each other. I have the following scenario:
Application A logs user in using Google Apps login
Application B logs user in using Google Apps login
then these applications need to communicate directly to each other (server-to-server) using some APIs
The question is: how do these applications verify that the other one is logged in with the same user to Google? I would imagine something like:
- Application A gets some 'token' from Google and sends it to Application B
- Application B verifies that this token is valid for the same Google account as it is logged in with
Is there a way to accomplish that via Google Federated Login? I am talking about Hybrid protocol here.
Here's a simple way to do it:
You keep everything keyed to the user's Google userid on both applications.
You share the data using HTTP requests that contain the userid.
To prevent leaking of the userids (forbidden by the account API) and to verify the messages really come from the other application, you encrypt the requests with a symmetric cipher such as AES or Blowfish or whatever you like. Both applications have the same key embedded.
You could public key cryptography. With just two applications, it's not worth it in my opinion. If you start having more apps, public key makes sense.
The fine print: encryption does not guarantee integrity or origin without additional measures. You need to take precautions against playback, for example by incorporating a time-stamp or sequence number. You need to take precautions against tampering, e.g. with a checksum. Make sure to use CBC and good initialization vectors. Keep the key secret.
user.user_id() is always the same across all the apps for the same user. So you can simply compare values returned by user.user_id(). Is this what you are looking for?
Note: Every user has the same user ID
for all App Engine applications. If
your app uses the user ID in public
data, such as by including it in a URL
parameter, you should use a hash
algorithm with a "salt" value added to
obscure the ID. Exposing raw IDs could
allow someone to associate a user's
activity in one app with that in
another, or get the user's email
address by coercing the user to sign
in to another app.
From docs

Securly Storing OpenID identifiers and OAuth tokens

I am creating a web app that will use OpenID logins and OAuth tokens with Youtube. I am currently storing the OpenID identity and OAuth token/token secret in plain text in the database.
Is it inappropriate to store these values as plain text? I could use a one-way encryption for the OpenID identifier but I don't know if that is necessary. For the OAuth tokens, I would need to use a two-way encryption as my app relies on getting the session token for some uses.
Is it necessary to encrypt the OpenID identity? Could someone use it to gain access to a user's account?
First, there is a registered application that has consumer_key and consumer_secret.
When users authenticate and "allow" your registered application, you get back:
an access_token that is considered the user's "password" and would allow JUST YOUR application to act on the user's behalf.
So, getting just the user's access_token from your database won't help much if they don't also have the consumer_key and consumer_secret for complete access.
The service provider compares all 4 parameters on request. It would be smart to encrypt these 4 parameters before storage and decrypt them before response.
This is just when you need to update or make changes to the user's resource owner on behalf of a user. To keep a user logged-in on your site, use sessions.
The OAuth Token and Secret should both obviously be kept safe in your database, but you can't store them using 1 way encryption the same way you would for a password. The reason being is that you need the token and secret to be able to sign the request.
This would also be the case if you are running an OAuth server, you still need the original token/secret to verify the request.
If you want to you could still encrypt them using a 2 way encryption algorithm such as AES to offer security in case your database or database backups get compromised.
There's two schools of thought here.
The first argument is that: you should treat OAuth tokens like passwords. If anyone were to access your database, obtain all the OpenID/OAuth pairs and run an man-in-the-middle attack, they could impersonate any user on your site.
The second argument is this: by the time someone has access to your database and sufficient access to your network to run an man-in-the-middle attack, you're hosed anyway.
I'd personally err on the side of caution and just encrypt them; it's a standard practice for passwords, so you might as well give yourself just that little extra peace of mind.
Meanwhile, Google has this advice:
"Tokens should be treated as securely as any other sensitive information stored on the server."
source: http://code.google.com/apis/accounts/docs/OAuth.html
And some random guy on the web has specific implementation advice:
If they’re on a regular disk file, protect them using filesystem
permissions, make sure that they’re
encrypted, and hide the password well
If they’re in a database, encrypt the fields, store the key
well, and protect access to the
database itself carefully. *
If they’re in LDAP, do the same.
archived post (original post URL, now a dead link)
OpenID URL shouldn't be encrypted because this is your "open id" literally, everyone should know the value. Besides, the URL needs to be an index in the database and it's always problematic to encrypt the index in the database.
OAuth token/secret should be secret and encryption may improve security if you have to store the token long term. In our OAuth consumer application, token/secret is only stored in session for a short while and we choose not to encrypt them. I think that's secure enough. If someone can peek into our session storage, they probably have our encryption key also.
Yes, these should be symmetrically encrypted (say, AES-256 in CBC mode) at rest in a database. A simple way to encrypt these tokens is using SecureDB's Encryption as a Service RESTful APIs.
Disclosure: I work at SecureDB.

Resources