Best way to save authentication token? - c#

I've been working on implementing an api in c#. The implementation is going well, but I did come across a concern.
When my library has authorized against the api I have a auth_token which I use for consequent queries to the webservice.
The token needs to be kept between program runs as it stays the same for the user (although I do check if it is still valid when the application starts).
For testing purposes I basically just save the token into a text file which is kept in the root directory of the app.
This works fine, but is this the best way?
Not sure the user will appreciate that it gets saved in a cleartext file (even if it is on his own pc).
So, what is general practice for saving tokens like this?

I would use the Windows Data Protection There are numerous examples around on how to use it from C#. It uses a user specific key to encrypt the data. Only the user themselves can decrypt it. Also be sure to secure the data during transmission between the server and the client.

Create a settings file for your project in the project properties, add a AuthToken property to the known settings (probably at the user level), then use:
Properties.Settings.Default.AuthToken = userAuthToken;
If you think they'll want it hidden, encrypt or encode the userAuthToken so it is less obvious.

You can verify if the api is used under asp.net or windows environment ( it's enough to check if Request is null) and on the first case use a cookie, on the latter save it on a registry key.

That may work in a local app or running the CI locally, but if you are in DevOps (Azure) your test app will reside in your VM bin folder. After every deployment your bin folder gets wiped out so the token you saved in your bin files is gone. Perhaps the best way to save it will be encrypted in one of your DevOps environment variables in your release pipeline so you don't loose it. When running locally you can save it anywhere.

Related

Store secret key securely in .NET Standard cross-platform app

I'm working on a C# PowerShell module, which is going to be a simple wrapper around some service REST API. I'd like to target PowerShell Standard / .NET Standard and make module available across all supported platforms.
For this app authentication requires API token, issued on a service website by the user. Entering key every time you open a session would be extremely inconvenient and therefore I need some way to securely store the API key in a user profile.
The problem is - I cannot find an easy way to encrypt data that has transparent cross-platform support. Initially, I wanted to use SecureString, but it is (a) deprecated and (b) doesn't seem to have good support on Linux. In a perfect world I'd like to have some mechanism similar to Windows encryption - user certificate encrypts API key and I put result in a text file in a user folder.
This is not a financial or mission-critical application, top-notch security is not required, but still keening plain text secrets in my home folder makes me nervous. Yes, I'm talking to you, AWS SDK authors :)
My first thought was: "just save secret key to ENV variables..."
But if I understood OP's question correctly, it is required to restrict unauthorized reading of this secret even on OP's machine.
One option I could see is just create a folder (or maybe file) and give it the access permissions only for one particular user. Ultimately one can create new user account which will be used to run the code in powershell and give this new user exclusive permissions to read secret file. This will prevent some 3rd party programs running from OP's account to read secret file.

Why should I use User secrets only in the Development environment?

I have to save keys out of project and repository. For this, I want to use User secrets. But it is written there,
Call AddUserSecrets only when the app runs in the Development environment, as shown in the following example
And I can't understand or find a cause. Why can't I use it in the Production environment?
You can find it in the link you provided to the User Secrets documentation:
The Secret Manager tool doesn't encrypt the stored secrets and
shouldn't be treated as a trusted store. It's for development purposes
only. The keys and values are stored in a JSON configuration file in
the user profile directory.
I think the short answer is that you probably could if you wanted to but that it is not what it is intended for.
My understanding is that the primary purpose of User Secrets is to keep credentials out of source control. In the days before GitHub and the cloud, most developers just stuck any and all credentials in the web.config and it was mostly ok. Then lots of people started using public repositories and AWS and all of a sudden https://www.zdnet.com/article/trufflehog-high-entropy-key-hunter-released-to-the-masses/
There are now a great many different tools out there for managing secrets, which one best suits your needs is a much harder question, but you could consider:
Are you using access controlled source control?
Are you cloud or on-prem for build and deploy?
Who has read access to the live servers?
How sensitive is the data you are storing?
What other applications are running on the server?
I was just poking around in the CreateDefaultBuilder method and found this, which is perhaps relevant:
if (hostingEnvironment.IsDevelopment())
{
Assembly assembly = Assembly.Load(new
AssemblyName(hostingEnvironment.ApplicationName));
if (assembly != (Assembly) null)
config.AddUserSecrets(assembly, true);
}
Obviously you don't have to use the default version and you could add secrets for all the environments, but there it is.
This is a development time only tool. Storing any kind of secret in a file is risky, because you may accidentally check it in. In production, you can for example use environment variables to hold secrets (or any other more secure mechanism.)
While environment variables are one of the most used options in web development there are some reasons why this may not be the best approach:
1.The environment is implicitly available to the process and it's hard to track access. As a result, for example, you may face with situation when your error report will contain your secrets
2.The whole environment is passed down to child processes (if not explicitly filtered). So your secret keys are implicitly made available to any 3rd-party tools that may be used.
All this are one of the reasons why products like Vault become popular nowadays.
So, you may use environment variables, but be aware.
User secrets are basically a JSOn File somewhere in your user directory. That works well on your dev pc. But on a production system, the values should usually be injected through more production ready configuration system(s), like Environment Variables, appsettings.json or a azure keyvault. Envs and appsettings are already activated per default.

C# - Class Library Project - Unable to update App.config file while building the project

I have a C# based Selenium project which has an app.config file. This app.config file has sensitive information which should NOT be made available in the code explicitly.
Is there a way to pass in the password to the app.config file before building the project.
The password can be supplied in the Build settings ( in variables section ) and can be made hidden.
Is there a way to read the values from the Process variables tab and update the values in the app.config file before building the project?
Or is there a way to send the password in an obfuscated/encrypted fashion using C#?
I cant user Replace tokens build step due to some constraints ( since it is a custom marketplace extension ) If there is a task by Microsoft which helps me in this scenario.
Thanks in advance for your help on this.
Your problem is just to secure Password am i right?
You can save your password into the machine registry to be hidden and encrypted.
You can use an external services to provide your secured password if we are talking about securing the password (Web Service or something).
This is just a suggestion. Just think about it.
I did many things. Nothing worked. At last I just encrypted the password made it available as a REST service. Invoked the service while running my test and Decrypted and ran it. Thanks all for your work on this.

How to share cookies between 2 windows accounts

Is anybody knows how to share cookies between 2 windows users?
I have a Windows 10, where have 2 users: one is admin and second is operator.
Admin is logged in into the system and then goes to the web site, where setup some config. In this config we have some specific value which should be store locally in machine and operator shouldn't know nothing about it. So he is set some kookie { someKey: someValue } and then log out from Windows.
After this operator log in into Windows and open the same website and he should have access to this cookie { someKey: someValue }.
I search around we and found nothing about it. Found only solutions about save to file system, send via tokens and save MAC address with a value into DB. But this is not suitable for me. I know that share cookies and store locally isn't secure, but need to implement that feature.
Web project based on chrome browser, asp.net mvc, angularjs and ms sql for db storage. Is anybody can help me with this issue about cookies?
There is no way to do this. First, every browser has its own way to store and retrieve cookies. It is impossible to write something that will work for any platform and any version.
Second, there is security. You can't just copy some files and expect this to work. Browser developers aren't stupid to leave such a big security loophole in their software.
You are mixing Windows applications with full control over the system with a web application that only resides within the browser. You should find a better way. You could use a certificate installed on the machine to validate the user, but it seems to me there are better options, like simply logging in, etc.
Cookies are a browser component that all major browsers locate in user specific directories. if you could change it to HTML5 storage API and you could setup the storage to a folder both users have access (dunno about this). You could have client side shared data. Most probably, you could not. And certainly not using cookies.
Disclaimer: I havent used storage API
Edit: Just checked. Storage API does store the data un user specific folders, so cannot use it either.
"In practice, "client-side storage" means data is passed to the browser's storage API, which saves it on the local device in the same area as it stores other user-specific information, e.g. preferences and cache. Beyond saving data, the APIs let you retrieve data, and in some cases, perform searches and batch manipulations." Source: https://www.html5rocks.com/en/tutorials/offline/storage/

load balancer question c# asp.net

The place where I work has 2 servers and a load balancer. The setup is horrible since I have to manually make sure both servers have the same files. I know there are ways to automate this but it has not been implemented, hopefully soon (I have no control over this). I wrote an application that collects a bunch of information from a user, then creates a folder named after the email of the user in one of the servers. The problem is that I can't control in which server the folder gets created in, so let say a user goes in.. fills his stuff and his folder gets created in server 1, user goes away for a while and goes back to the site but this time the load balancer throws the user into server 2, now the user does something that needs to be saved into his folder but since it didn't created in this server an error occurs. What can I do about this? any suggestions?
Thanks
It sounds like you could solve a few issues by implementing a cloud file service for the file writes such as Amazon S3 http://aws.amazon.com/s3/
Disk size management would no longer be a concern
Files are now written and read from S3 so load balancer concerns are solved
Benefits of a semi-edge network with AWS. (not truly edge but in my experience better than most internally hosted solutions)
Don't store your data in the file system, store it in a database.
If you really can't avoid using the file system, you could look at storing the files in a network share both servers have access to. This would be a terrible hack, however.
It sounds like you may be having a session state issue. It sounds odd the way you describe it, but have a look at this article. It's old, but covers the basics. If it doesn't try googling "asp.net session state web farm"
http://ondotnet.com/pub/a/dotnet/2003/03/24/sessionstate.html
Use NAS or SAN to centralize storage. That same network-accessible storage can store the shared configuration that IIS can be setup to use.
Web Deploy v2 just released from Microsoft, I would encourage the powers that be to investigate that, along with Application Request Routing and the greater Web Farm Framework.
This is a normal infrastructure setup. Below are the two commonly used solutions for the situation you are in.
If you have network attached storage available (e.g. Netapps), you can use this storage to centrally store all of your user files that need to be available across all servers in your web farm.
Redesign your application to store all user specific data in a database.

Categories