Does Cognito authentication send hashes over the wire? - amazon-web-services

I'm using AWS Amplify (if that makes any difference, I assume the backend APIs control this regardless) and would like to understand if when a user logs in their password is sent in plaintext (albeit within a TLS connection) or if it's hashed - and if so what the hashing algorithm is.
Does anyone know? Thanks.

In my experience (I don't have anything written from AWS to back this up) Amplify sends a USER_AUTH followed by a password challenge similar to SSH. That means the password is not send over the wire, not plaintext and not hashed. The method would be similar to what is explained here: the client proves that it has the password by answering a challenge. A hashing mechanism is used, but the hash used is not a hash of just the password.

Related

Encryption of a Password send over HTTPS

Good day,
I am very new to database/application/connection security and would like some help on a project.
Let me explain my environment :
I have a username A and password A being saved in a database (A) on a local machine.
Password A is being stored using a type of hashing algorithm with salt A.
I am sending the credentails (Username A and Password A) via a HTTPS SOAP Call to a webservice sitting remotely.
Apon receiving Username A and Password A the webservice validates those credentials to a table sitting in database (B) local to the webservice location.
My Problem : If someone gets access to database A and extracts the hashed passwords they can use a SOAP request to connect to the webservice. This means that my security is null and VOID.
I have to possible solutions :
SOLUTION 1 : Before sending password A to the webservice, I decrypt it and send it over plaintext via the Secured HTTPS connection. The webservice will then encrypt it again when validating agains the hash stored in database B.
SOLUTION 2 : Before sending password A to the webservice, I do a second encryption to that existing hash. When arriving at the webservice, it is decrypted to expose the hash which is .then validated against database B.
My Question : Is any of the 2 solutions above, best practice. If not, what would be a best practive solution for this scenario.
Kind Regards
Just a few notes
there is difference between hash (one way, non-reversible) and encryption (reversible). You cannot decrypt hashed value.
I will assume you are working with service credentials, not user's identity credentials
Here I will assume you are talking bout
SOLUTION 2 : Before sending password A to the webservice, I do a second encryption to that existing hash. When arriving at the webservice, it is decrypted to expose the hash which is .then validated against database B.
The hash effectively becomes a password, it doesn't add any security to the solution
SOLUTION 1 : Before sending password A to the webservice, I decrypt it and send it over plaintext via the Secured HTTPS connection.
There are several standards to authenticate the SOAP WS client, using simple credentials it's WS-UsernameToken. Effectively the client sends its username and password plain, relying HTTPS to handle the channel security.
My Problem : If someone gets access to database A and extracts the hashed passwords they can use a SOAP request to connect to the webservice
One the password is hashed, you won't be able to decrypt it, but as well you cannot use the hashed value as a password. Otherwise you will get the "solution 2" and you are using the hash as a password.
Indeed, this is generally a problem. You may search other questions, how to store service credentials locally. The whole problem is - you need to store the credentials. In my experience the best you can do at least make retrieval somewhat harder, e.g. encrypt the service passwords so they are not stored plain in the database or config files. At the end the client application needs the encryption key somewhere to decrypt the credentials. The key needs to be protected as well.
If you are dealing with user credentials (user identities), do not store the user passwords at all at the client side, there are other ways how to authorize user actions (access token, jwt token, ..)
If you are using xml based SOAP you can use WS-Security to encrypt the password and sign your request data so that the integrity and security of your password is ensured, and the send the data over https.
For storing passwords you should use irreversible crypto hash like sha2, at server you will decrypt the password, create sha2 hash and match it against the one from database

Validating the password requested during sign up with AWS Cognito User Pool

Is there a way to see the password within the Lambda triggers that can be fired off by a sign-up or password change on AWS Cognito User Pool?
I want to get the password and compare it to lists of previously compromised passwords (the haveibeenpwned lists) to ensure password strength at a much higher level than what is possible by the arbitrary complexity rules that can be defeated by garbage like "Password!23"
The answer is that it currently is not possible to do as simply as I had hoped.
What you would have to do is to turn on the USER_PASSWORD_AUTH type authentication flow which means the password is sent in the HTTP POST request and setup your own reverse proxy to take the request, check the password details and then forward the request onto Cognito, accept the response and then send it back to the browser.
Or just turn on the "Advanced Security Features" option that they give you and tick the box for checking passwords against compromised lists... which is what I imagine AWS is trying to force you to do.
If you are using Amazon Cognito than you should not take worry about passwords and its complexity. It is totally managed by Cognito.
Your authentication will be based on Tokens only :)
There is no way to retrieve the password from lambda trigger.
But yes, You can do one thing, Set status to FORCE CHANGE PASSWORD. So that user must have to reset password after first login.
After that, whenever your user try to change password, You can add your own constrains in your UI before calling ChangePassword API
I hope this helps!

Can I use a hashed password as the secret for generating a hmac?

I think it would be very comfortable to use the user's password hash as the secret for generating a hmac. Why is OAuth and others using tokens and nonces?
I think of something like this:
Client enters a password in the ui.
The application registers with the webservice using the hash of that password, which is stored on the server.
Form now on that hash hasn't to be transmitted again.
The client can always regenerate the secret by asking the user to enter the password and hashing it. Every message is signed with this hash, the server can look it up by username or guid and check if the sent mac is valid.
A intruder on the server can get that hash, but doesn't know the users real password, anyway he could send valid request with that hash. But this is not likely to happen, the saved hashes could also be hashed again using a nonce. Anyway because the pwd-file will be on a client's server it should be obfuscated using e.g. base64 to avoid the file looking like {"password":"a4bd146hashhashhash"}.
Most of all the real password of the user won't ever be transmitted. The request's will be secured with a timestamp/token against replay (I recognize the purpose of the token here).
Sending a hash would be perfectly applicable for me because the client will never be a simple website with a tag e.g.. The webservice will be used in a ajax-based application and a java desktop application, both of them capable of hashing strings...
What's wrong with that? It's so simple, more RESTFul than anything related to authentication, and i think yet effective. What am I missing?
Greets, kruemel

What is the best way to store password in database when API call requires sending of password in plain text?

I'm writing a web app in Django that is interfacing with the Read it Later List API (http://readitlaterlist.com/api/docs/). However, all of the API calls require sending the username and password with each request. In order to do this, it seems that I need to store the user's password in plain text in my database. Am I missing something or is that the only approach possible in this case? Is there some way to store an encrypted password in my database, but yet be able to send a decrypted version of it when making the API call? If not, then are there any best practices that I should be following to safe-guard the user's password?
I'm pretty sure that this can't be the only service requiring sending password in plain-text. I'm interested in knowing how developers deal with these sort of services in general. I'm new to web development, so any help or pointers is appreciated.
do your users have to log into your website to use it? if you also are making use of a password authentication scheme, you could piggy back on top of that. Use the login password for your site as a cipherkey in a symmetric key cipher to encrypt the api password. then you need only store a hash of the users password (to your own site) and an encrypted password for the remote api.
Never save password in plain text. You can encrypt and decrypt the password but the problem is that the key you use to do the encryption and decryption will generally be accessible to anyone who has gained access to your server so it's not secure.
An alternative is to ask them to enter their password and save it in an encrypted cookie, or session variable or something else that will expire when they have logged out of your app. This has the drawback of them having to enter their password every time they user your app.

Authentication for Both Webapplication and WebService

I'm currently working on an application consisting both of a webapplication and client software. The client communicates via webservices, supporting both a SOAP and Protobuffer implementation.
The initial registration is done via the webapplication, which relies on username + password authentication later on.
After finishing the registration process, all features are also available via the client, which will only communicate via HTTPS. For authenticating webservice calls, I'm currently thinking about three possible approaches:
Including the username and password in every message. But is it really a good practice to include the credentials in every request, even though secured by HTTPS?
Providing the username and password in the first webservice request. The client then gets a token which is used for all future requests. (Note: It's not deemed acceptable to force the user to copy a server-generated token to the client application.) Only if the user revokes the token, he needs to send his username and password again for getting a new token. Such token based approaches seem to be quite common, for example Google, AWS and Rackspace are using them a lot. But does it really pay off in this scenario?
Hashing the password on the client sounds like a good solution. However I'd like to salt the encrypted passwords on the server-side. Adding requests only for fetching salts doesn't sound like an optimal solution or is it?
Are there any best practices or tips? I couldn't find too much information exactly for these requirements.
Currently I'd go with 2), but I'm not really convinced yet.
The project is based on Java, Apache CXF, Protobuffers and Shiro, but shouldn't have too much of an impact for the general question...
If you're only concerned by authentification and neither by confidentiality nor integrity, you can handle it by securing:
HTTP transport level, using HTTP BasicAuth (user+password on each message) + eventually HTTPS for confidentiality, however as you noticed (solution 1) it it is kind of old school and keeping user/password in local cache is not a big deal but cannot be advised.
Message level (the soap message) using Security Token for instance but I do not know Protobuffer
Application level (solution 2 and 3), that is the way Google, Amazon, Ebay and others are working. You will not ask the user to copy/paste his token, you will generate one from user/password
I would securing the application level using a token, since getting a salt from the server is almost like getting a token and does not add more security (a secured salt should be known from only you, and if channel is protected it mean getting the token from given password and username is secured as well).
A better but more complex solution would be usage of SSL certificates, available both in browser and client software.