Desmond
Desmond

Reputation: 587

how to securely store a password for a 3rd party service in django?

I'm running a web service on Django. Users register to my system and provide me login details (username and password) for a 3rd party web service).

My purpose is to store this details in the best and safest way. Unfortunately my service needs this data for some offline scripts that query the 3rd party service, so I cannot store the login/password encrypted with user password (and use it to a key do decipher them.

I read lots of articles on stackoverflow, but most of them (like: What is the best way to store password in database when API call requires sending of password in plain text?) do not need an "offline" access to this data.

The only idea I have is to have these details stored on a very secured server, that only accept request from my django server, and tunnel their communication with tls.

Do you have any other ideas?

Thank you in advance!

Upvotes: 3

Views: 3480

Answers (2)

AppHandwerker
AppHandwerker

Reputation: 1788

This is an old one but the way to go would have been to encrypt the password before you stored it. Using a key stored securely (i.e. not in the DB (or at least not in the same one) and not in Github) and to load that into the environment where the project was deployed. This way anyone gaining access to the DB directly wouldn't be able to read the password.

possible source of more info

The Cryptography library is a good one to use, and is referenced in the article above.

For the case described in this question, I would have place an encryption key in the environment and loaded it to settings.py on deployment it would look something like this:

generating a key

from cryptography.fernet import Fernet

key = Fernet.generate_key()

You could run the above, if the library is installed in to your Python environment, in a python console.

Depending on how you deploy the app you would need to provide access to the key to it. Below is one way to get it into your environment:

export ENCRYPTION_KEY="<key>"

Once you have it in your environment in settings add this line

ENCRYPTION_KEY=os.get("ENCRYPTION_KEY")

How to use the key? Depending on your setup you could write additional property method on your model to get and set the value of the field, something like

 class mymodel(models.Model):
    
  ....
  @property
  def password(self):
      f = Fernet(settings.ENCRYPTION_KEY)
      password = f.decrypt(self.<myfield>)
      return password

  @password.setter
  def password(self, password):
      f = Fernet(settings.ENCRYPTION_KEY)
      token = f.encrypt(<password>)
      self.<myfield> = token
      self.save()

Other options could be to subclass another django model field and add the functionality there. If you're only doing this in one place then the above should be fine.

How you store the Encryption Key is up to you the environment is just one option. Key here is to keep it somewhere safe and importantly don't lose it... or good luck ;)

Upvotes: 1

PurpleAlien
PurpleAlien

Reputation: 906

First and foremost, the other articles are correct: never store passwords in plain text. If you come to the conclusion that you need to store them in plain text, you need to rethink your strategy (Oauth?). The whole reason for using hashed passwords with salts is that even if things go wrong, the passwords are safe (since there are no passwords, only hashes...). I'm actually wondering for what reason exactly you need these third party usernames and passwords?

If you really must store these, use an encrypted file or database field and make it so that whenever your script runs you need to manually enter the decryption password. I assume here that you don't run this script every 5 minutes, but once a week or so. Besides that, make absolutely sure that the server doing this is not doing anything else and has no other local users, otherwise it would be possible to analyze memory for instance and find the decrypted passwords.

In all, I would still say that what you're attempting is very, very dangerous, and you should proceed very carefully...

Upvotes: 1

Related Questions