I have the following use case:
My web application is used for creating prescriptions. When I send the prescription creation request to the government API it is signed with the current user's certificate. The certificate is stored on the application server and is encrypted with a password which only the user knows.
Users want to be able to store their password in my app temporarily so that they don't need to paste it in for each prescription they create.
What would be the most secure way to store this password? Couple of ideas:
Local storage in the browser.
Bad because anyone with an access to the user's device can see the
password even if they're not logged in. Also if the app is not running I have no way to clear the password if the desired storage time expires.
Frontend app memory.
Bad because if user refreshes the page or opens another tab the stored password is gone.
Backend, in database
This sounds like the best option because I can encrypt the password. Is it even worth encrypting though? I would have to encrypt it with some key stored on the same machine so if someone gains access to this machine the encryption doesn't matter because they would be able to decrypt it quite easily.
Separate the password encryption key and the encrypted password:
Generate and store a random key (and nonce / salt)
Encrypt the password (e.g. AES-256-GCM) with the random key
Store the encrypted password on your backend
Send the random key with the request to temporarily decrypt the password
Delete the encrypted password on the backend when the session expires
That way:
The random key stored in the browser can only be used within the current user session and is useless on its own
The encrypted password on your backed can only be used with the random key stored in the browser and is useless on its own
What is the best practice for securely storing authentication credentials in a web extension? e.g. The user enters their username and password, and the extension saves these credentials in order to authenticate to an API in the future.
Currently, I have been using the sync storage, but was wondering if this has the same level of protection as saved passwords in the browser (for example, getting encrypted with a master password)?
Or, is there a method to store/retrieve the login details in the browser's password storage (but, obviously not being able to retrieve any other passwords)?
Do any of the answers above change if storing an API token, rather than full login credentials?
I'm implementing authentication for a ASP.Net MVC5 Page using ASP.Net Identity 2 and LDAP as storage for the users. I'm not using OWIN.
I started to create my own IUserStore deriving from IUserPasswordStore. This interface needs to implement three methods:
GetPasswordHashAsync
SetPasswordHashAsync
HasPasswordAsync
I'm now wondering how to verify the passowrd for a user since UserManager only offers a CheckPasswordAsync method which accepts the user object and the entered password. My assumption how this works is as following:
This method uses the Passwordhasherand it's VerifyHashedPassword method.
VerifyHashedPasswordthen receives the hashed password provided by IUserStores GetPasswordHashAsync method.
Therefore I could implement my own passwordhasher and verify the provided password against the saved password hash
If this assumptions are right and this could be a solution I'm wondering about security. What is the correct place for performing hashing and verifying this hashes... should all happen inside the LDAP (the solution wouldn't work) or is it better to hash a password before sending to an LDAP for storage and then check the hashed password by myself?
Could retrieving passwordhashes from the LDAP be an attack vector for at least fetching the hashes?
Does a complete different approach within ASP.Net Identity exist for authentication against an LDAP? I know that there is a possibility for authenticating against an external mechanism, but I expect that this is designt for login by Google/Facebook ect. which present an own credentials input form and therefore not suitable for LDAP.
I'm looking for detailed insight into how does sites like mint.com and sigfig.com (etc.) secure credential information. Millions of people trust not just their login information to the primary site, but also their FINANCIAL sites, and not just one but often MANY financial sites.
This is a question at the architecture level. The sites obviously employ penetration testing, active monitoring etc. And they must be doing strong encryption such as:
https://crackstation.net/hashing-security.htm
If a small business/web site wanted to be as secure as possible storing this information, how would they go about it?
So you want to store user's passwords to external sites securely...
You can't use hashing here, because you need to know the plaintext value and send it to the external site to login.
Ideally you'd use something like OAUTH here instead, but not every site supports OAUTH.
Here's what I would do:
Encrypt the external.com credentials with a key derived from my password for you.com (I need to be logged in to you.com for you to grab data from external.com)
I create an account with you.com with a username and password and login
You hash my you.com password and store in the db
Each time I login, you generate a key derived from my plaintext password, which you keep in server-side session while I'm logged in
I add credentials for external.com
You encrypt these credentials with my you.com key and store in the db
You decrypt my external.com credentials with my you.com key and then login to external.com on my behalf
An even better approach would be to add a second server that only stores the external credentials and connects to the external sites and returns authentication details (like a session cookie).
I am setting up a website to use Google's OAuth2 interface for user authentication. The website will store private data associated with each user - which I'm planning to encrypt.
If I implemented my own authentication method for the website, I could easily derive a key from the user's credentials (which include the user's password), allowing the data for each user to be strongly protected. But with OAuth2, I believe I can only receive an access token, granting that user permission for a period of time - the problem is that the access token value will change over time.
Is there a way that OAuth2 can provide me with an immutable secret tied to the user which I can use to derive a secure key from? Or is there some other method of creating a secure persistent secret using OAuth2?
--- Edit ---
In response to the questions and comments, here are some thoughts to consider:
All user information should always be protected with strong encryption and user authentication - the reason we read so many news articles about website & database hacks is because developers say "do we really need to secure that" and then respond with "No - because no-one but us will be able to access the database, security is hard, etc". The hacker downloads the database et violá. Credit cards, email addresses, phone numbers, passwords, you name it, then become compromised.
There are only two real secrets - one is a password stored in someone's head, the other is a strong random value that only the authorised user has access to (like a physical token). If you think a secure key can be derived from an email address alone, or that a secret needs to be stored in a database, you don't really understand security.
I guess what I was trying to discover was whether an OAuth provider can provide to the OAuth client an immutable value securely linked to both user and client - effectively, this would be a key that could only be unlocked by the OAuth provider using a combination of the user's secret (their authentication password) and the client's secret (used in the OAuth protocol). The client could then use this value to provide a reasonable level of security for the user's data.
Of course this implementation is not perfect from abuse, but implemented correctly, could provide a reasonable way to secure data whilst still using the good practices of the OAuth scheme.
The point of the token is that you can then use the token to obtain information from Google about the user. During the initial authentication, you will tell the user, and google, that you want to access certain information about the user:
https://developers.google.com/+/api/oauth
Assuming that the user allows you to access their information, such as their email address, you can then get their email address from google. Once you have their email address, you can generate a secret key for their user, store this in your user table, and use it to encrypt their data. Then, when they login again, you can lookup their email address and find their key.
Is there a specific need for the immutable information be 'secret'? Or is it just a key to identify a user?
If the information that you're storing is truly private, and you want to make it so that you can't access your user's data, then all you have to do is store the encrypted blob for your users. Once the user had downloaded their data, they can use their key to decrypt the data client-side.
My first question would be: Why do you want to derive your encryption keys from some tokens?
The tokens and your encryption keys could remain independent and can be associated to a user identified by a unique id. User authentication can be done by whatever way you need either via credentials or open ID authentication or something else. But, once a user is authenticated, your decryption APIs can fetch the decryption key associated with the authenticated user and do whatever decryption it has to.
This way you can potentially allow users to tie multiple open ID accounts with the same user similar to what Stackoverflow does. I can associate my yahoo, facebook and google accounts with my Stackoverflow user and can sign in with any of those providers. I can disassociate those accounts any time I want. But that does not affect my Stackoverflow profile and data.
So, it is not a good idea to derive your keys from something that is not constant and keeps changing. Instead, keep them separate.
If I implemented my own authentication method for the website, I could easily derive a key from the user's credentials
This schema has a terrible weakness - if a user forgets /resets its credentials, the key is lost forever
Is there a way that OAuth2 can provide me with an immutable secret tied to the user which I can use to derive a secure key from?
OAuth2 is an authorization protocol. It is not intended to give you any user secrets.
the Google's OAuth2 should provide a user info service returning username (email) and some id (sub).
However these are identity information, not any secrets. And mixing user credentials is imho bad idea (as already mentioned), using an external IdP (google) you will have no access to credentials tat all.
And now what?
My suggestion:
If you really want to encrypt user's data using a user-provided secret, let the user provide the secret or encrypt the data encryption key by the user itself (or using user's public key?). The user must be aware that if this secret is lost, the data will be unaccessible. It is quiet uncomfortable in long run. Some DMS systems use this approach to encrypt the stored sensitive documents.
if you want to encrypt data in rest (on the server, database), you may have an application specific key, imho best stored somewhere else (key vault, key management service,..). Indeed then there is a different risk profile (you have to protect the key,..) but it's much more convient for users. This is usually good enough along other security measures (even big enterprises don't ask for a separate password to encrypt your credit card number or email)
What you need is constant secure (random) key for each user that you could get from authentication service that gives OAuth2 endpoint (in this case - Google).
OAuth2 protocol itself does not provide such value - Authentication server uses generated values that are not constant. But OAuth2 does not prohibit from giving this value from Resource server (together with user id, email etc). So basically OAuth2 lets you secure data in the way you want, but Google, which you currently use, does not give this type of constant random value.
Also note, that this would not work if you would let user relate few accounts, like Google and Facebook, as they would give different random keys.
If you derive secret from credentials, this would also mean that resetting password would reset user account.
Furthermore, if you encrypt data like emails in this way, it becomes impossible to decrypt them without currently signed-in user. So emailing newsletter becomes practically impossible. You cannot query the data in SQL also.
I could only suggest some countermeasures:
Do not store sensitive data at all, or store it hashed. Passwords must be hashed, not encrypted. Do not store CC numbers, store tokens that represent them.
Use encryption with key, stored in another data source. This adds at least some security - attacker must get not only DB copy, but also encryption key.
As data is encrypted, storing it in database is no longer necessary. You can store encrypted data in files or some other source, where it is safer than in DB (no risk of SQL injections etc)
I've been having this same issue. So far, I can't find a secure way around it.
Basically, we need a per-site randomly generated secret provided only with implicit flow that can be used to derive credentials to access systems and decrypt data.
Because I want to protect the data from myself, I could write the client to salt/hash the secret in two ways, one way to retrieve the data and another to decrypt it.
Alas, this is not the case.
I could derive credentials from things in the basic scope of the oAuth and that would protect the data against me, but that leaves the user wide open for cross-site vulnerabilities, and besides, personally identifiable information makes for a poor secret.
The best I got is to use implicit flow oAuth2 to acquire the user's email address, randomly generate a client side secret, and force the user to email themselves the secret (as a recovery key), then store the secret in localStorage. Salt/Hash the secret + oauth scope variable to derive the credentials client side (so the user must be logged in) needed to access, encrypt and decrypt data.
If the user ever clears their localStorage, they need to go click the link in the recovery email, which places the secret back into localStorage.
This places the scope of vulnerability back on the client, but is resistant to public machines (would have to know who was logged in last, and get access to the localStorage token), allows for recovery, and weakly requires the user to be logged in. Still vulnerable to plugin injection attacks and physical access + knowing the user.
Update: I have decided to use some oAuth extensions (hello.js, folder APIs) to store the keys in the user account as files. It requires some permissions and some APIs to implement, but appears to be viable.