DEV Community

Andreas Jakof
Andreas Jakof

Posted on

Managing Credentials

I guess we all can agree, that storing Credentials in Code is a really, really bad idea! Not only can you reverse engineer the assemblies, but with Azure DevOps (or GitHub, ...) you can read the credentials in the clear.
Obfuscation does not help either, so if I ever see something like

private static string _password = @"klksndfl";

I think I'll cry!

But the question stands, how to access other systems with credentials, without having them in the code.

Well you have a couple of options here:

1. Storing the credentials somewhere else

This is the most obvious and easiest approach. Removing the credentials from code, but leaving them in the clear in another file, that is read during runtime and contains the credentials.
The application runs in a user context, therefore the file must be readable by the user, the application is running as. Forbid everyone else and you already have a very basic security. At least more than in code.
Make sure, to never check it in or you haven't won anything.

2. Encrypting it in the code

With encryption you can choose between symetric and asymetric ... or (like in S/MIME) use a combination of both.
No matter how you decide, there will be always the question, how to secure the parameters for encryption. If you save them in the code, you could have saved your credentials in the clear.

Well, if you choose asymetric, there is a way by using X509Certificate2.
First of all, asymetric is not cheap, that's one of the reasons S/MIME uses a combination of both. But, since we have only very small amounts of data (credentials usually are much less that 1 kb), we still can use it.
This little class of mine takes the properties from a directly derived class and stores them into an asymetrically encrypted base64-string or a BSON encoded asymetrically encrypted Stream.
There is a readme, showing how to use it.

It served me very well! Rest in peace little helper. ... but now we use another option:

3.Azure Key Vault

When runnig in Azure loading from an Azure Key Vault is as easy as these few lines.

private static T LoadFromKeyVault<T>(ref T creds, string credentialName, string version) 
where T : class, new()
{
  if (creds == null)
  {
      var astp= new AzureServiceTokenProvider();
      var kvc = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(
                    astp.KeyVaultTokenCallback)
                );
      var secret = kvc.GetSecretAsync("https://<YourKeyVaultName>.vault.azure.net/", 
          credentialName, 
          version).Result;
      creds = JsonConvert.DeserializeObject<T>(secret.Value);
   }
   return creds;
}

You manage the access in the KeyVault itself with Managed Identites.
So only allowed and managed Principals (Users/Apps) are able to get to your precious credentials while TLS secures the transport.

Oldest comments (7)

Collapse
 
kazepis profile image
Dr. Nikolaos Kazepis

Great read! I have a question though that is yet to be answered. Even if I encrypt the credentials in the source code (when azure is off the table), can’t a malevolent hacker steal the encrypted credentials and use them to access the underlying systems the exact same way as the source code does?

Collapse
 
andreasjakof profile image
Andreas Jakof • Edited

The Hacker can steal the encrypted credentials. But since you have it protected with a certificate using asymmetric encryption. Let him/her have some base64 string. Without the corresponding private key from the certificate it’s worthless.
Or did I not understand you correctly?

Collapse
 
andreasjakof profile image
Andreas Jakof

Of course you need some useful key lengths... make them at least RSA4096 or 368 bit for elliptic curves.

Collapse
 
kazepis profile image
Dr. Nikolaos Kazepis

Actually I was thinking on the premises of the front end. The front end application needs to access a back end api which is protected, hence the need of credentials. If I encrypt the credentials how does it help me? The credentials must be accessible by the front end (think of an angular application), the front end must send them to the back end to get a jwt and I can’t think of why it makes any difference whether they are encrypted or not. Is there any solution to this problem? Thank you very much for your time and effort!

Thread Thread
 
andreasjakof profile image
Andreas Jakof

Ahhh... In the front end scenario, there is OAuth2.0 to validate the user context and grant access. Then the backend(s) accepts that token.

But these kind of credentials are not the focus of the article.
It is intended for backends to keep your credentials out of code.

Thread Thread
 
kazepis profile image
Dr. Nikolaos Kazepis

Alright! I just brought this up because in this case you will also need a client_id and a client_secret and finding the right place to store them in order for the oauth server to be able to issue a token is a nightmare!

Thread Thread
 
andreasjakof profile image
Andreas Jakof

Well ... if you use a client_id with secret, then this should be in the backend. Otherwise use the user grant flow or use both to have it (like in azure) validated as the intersection of user and application rights.

If you put the client_id and it’s secret into the web front end and use this as the only access restriction, you might as well use an API without authentication/ authorization.