Joseph
Joseph

Reputation: 13188

How to safely store users' credentials to third party websites when no authentication API exists?

I am developing a web app which depends on data from one or more third party websites. The websites do not provide any kind of authentication API, and so I am using unofficial APIs to retrieve the data from the third party sites.

I plan to ask users for their credentials to the third party websites. I understand this requires users to trust me and my tool, and I intend to respect that trust by storing the credentials as safely as possible as well as make clear the risks of sharing their credentials.

I know there are popular tools that address this problem today. Mint.com, for example, requires users' credentials to their financial accounts so that it may periodically retrieve transaction information. LinkedIn asks for users' e-mail credentials so that it can harvest their contacts.

What would be a safe design to store users' credentials? In particular, I am writing a Django application and will likely build on top of a PostgreSQL backend, but I am open to other ideas.

For what it's worth, the data being accessed from these third party sites is nowhere near the level of financial accounts, e-mail accounts, or social networking profiles/accounts. That said, I intend to treat this access with the utmost respect, and that is why I am asking for assistance here first.

Upvotes: 5

Views: 1602

Answers (2)

gallen
gallen

Reputation: 1292

In addition to what 2ps said:

There is a project called django-cryptographic-fields that handles storing encrypted data in a Postgres database using Django.

As noted in their README from the link above:

django-cryptographic-fields is set of fields that wrap standard Django fields with encryption provided by the python cryptography library. These fields are much more compatible with a 12-factor design since they take their encryption key from the settings file instead of a file on disk used by keyczar.

While keyczar is an excellent tool to use for encryption, it's not compatible with Python 3, and it requires, for hosts like Heroku, that you either check your key file into your git repository for deployment, or implement manual post-deployment processing to write the key stored in an environment variable into a file that keyczar can read.

Upvotes: 2

2ps
2ps

Reputation: 15936

There’s no such thing as a safe design when it comes to storing passwords/secrets. There’s only, how much security overhead trade-off you are willing to live with. Here is what I would consider the minimum that you should do:

  1. HTTPS-only (all passwords should be encrypted in transit)
  2. If possible keep passwords encrypted in memory when working with them except when you need to access them to access the service.
  3. Encryption in the data store. All passwords should be strongly encrypted in the data store.
  4. [Optional, but strongly recommended] Customer keying; the customer should hold the key to unlock their data, not you. This will mean that your communications with the third party services can only happen when the customer is interacting with your application. The key should expire after a set amount of time. This protects you from the rogue DBA or your DB being compromised.
  5. And this is the hard one, auditing. All accesses of any of the customer's information should be logged and the customer should be able to view the log to verify / review the activity. Some go so far as to have this logging enabled at the database level as well so all row access at the DB level are logged.

Upvotes: 3

Related Questions