I am developing a web service and I need to send a username and password to the service in a GET method. Is it OK to send this information in the uri as long as it's going over a secure channel like ssl? In other words, can I have a uri that looks like /users/{username}/{cleartext_password}?
Edit: Sorry, I think I was unclear. The web service is essentially just a database of usernames and hashed passwords. Imagine a desktop application that keeps usernames and passwords in a remote database. The end user types their username and password into the application and the application accesses the web service to authenticate the user.
So, the application will need to send an end user's username and plaintext password to the service. The service will take the username and password and check that the username and the hash of the password match the username and hashed password in the database. The application itself will have to authenticate before it can access the service, but I am just wondering what is the best way to send the end user's username and password to the service for authenticating the end user. I don't to use a POST method because I am simply authenticating and therefore not changing the state of the server. Sorry for the confusion.
Do this.
Send a "key" and a "digest".
The "key" is equivalent to a username.
The "digest" is a SHA1 (or MD5) hash of the key, the URI and a "shared secret" or password.
When the server gets this, it computes it's own version of the digest, based on key, URI being requested and the "shared secret" or password. Failure to match digests is a 401 error response.
If it's going over a secure channel, there's no problem sending the username and password as cleartext. I'd just recommend against ever sending them as cleartext through an insecure channel and against sending them repeatedly for each request.
What you could do is first authenticate to the web service (send the username and password via ssl as cleartext) and get a token from the server that it will recognize. Then send that token with each subsequent request.
Generally speaking this is not a good idea... This data will be present in a number of log files, consequently the data could be visible to people who should not see it. At the very least you should hash or encrypt it before sending it if you can.
Here is a related discussion for a little more detail... Is an HTTPS query string secure?
SSL does encrypt the URI, but definitely take a look at some alternatives.
HTTP Basic Auth is nice and simple, and well supported by browsers, webservers, etc
It also won't end up in log files to the same degree as URIs
NB: It's just some plain-text HTTP Headers, so definitiely NOT recommended for non-SSL apps.
http://en.wikipedia.org/wiki/Basic_access_authentication
Related
I have a REST server over SSL.
Initially, the client logs in with the credentials.
To avoid sending the username/password for each request, I have created a custom token which is returned to the user in the login procedure.
This token contains some information about the client (IP and user-agent) as well as an expiration time; and of course the token is sent encrypted.
Further calls include the token in a custom header field; which are verified in IDispatchMessageInspector
The approach works fine, but I am pretty sure it's not a good approach.
Is there any benefit in using custom authentication than the message inspection?
Message inspection is the checking, changing, and replacing of messages after they are received and before they are sent.
Custom authentication requires the authentication of a username and password, which is more suitable for login or other situations where a username and password are required.
Both types of verification have their own applications.As you said to avoid sending the username and password every time you can choose message inspection. Personal words also tend to be message inspection.
I am trying to authenticate users for my Flutter app with hashed credentials. That is I'm hashing them before requesting auth with .login(). Problem is that the hashing packages I'm looking at using both have a function for checking the plain text password against the stored hash. This works fine for offline auth, however when sending hashed credentials to Parse auth gives invalid username/password error of course, because the algorithm changes after app restart.
The local side of things is pretty easy, now I'm caught wondering if it's secure to send users credentials in plain text through https Parse request?
I can't see a way to verify equality of hashing just entered credentials with parse because the hash is always different on app restart. Do I have any other option here?
Can someone give me some guidance here please?
For token based authentication for any service, first we have to send username/password in the request. Doesn't this cause security issue? How can we overcome this security issue of passing username/password?
The initial request which contains the username and password is no more or less secure than subsequent requests which would instead be bearing some sort of token. The solution to this problem, really to sending any type of information across the network, is to use two way SSL/HTTPS. With HTTPS, information being sent gets encrypted on the client machine, and then (in theory) only the server would be able to read what is contained. So, sending the plain text username and password might seem insecure, but if using HTTPS, then in fact it is secure.
I don't understand the point of having access token in authentication. Below is a paragraph of explanation I took but I still confused. Since every api call still go to the db look for the token, what's the different check for the username and password for every http request?
Instead of forcing clients to send username and password with every
request you can have a "get_access_token" function in your RESTful
service that takes the username and password and responds with a
token, which is some sort of cryptographic hash that is unique and has
some expiration date associated with it. These tokens are stored in
the database with each user. Then the client sends the access token in
subsequent requests. The access token will then be validated against
the database instead of the username and password.
Using the access token limits the amount of time the username and password are being used and sent across the wire.
How many times do you want your username and password, SSN, or other sensitive data do you want being stored and transmitted? Do you want that on every request?
First of all, access tokens are typically validated by checking the digital signature, which does not require the receiving service to talk to the issuing server. The client gets an access token once and uses it until it expires.
But even if the token had to be checked against the database on every call (when using reference tokens for example), tokens are still preferred over sending username and password on each call. They remove the need for the client to keep the password in memory (or elsewhere), where it can easily be stolen.
(1) Access token is less sensitive than your password. Access tokens typically expire after a short time (this is a requirement in the Oauth threat model), whereas passwords tends to be long term. If somebody grabs your access token, there is limited damage they can do. If they grab your password, then there is a lot of damage that they can do. Especially if you use the same or related passwords on multiple sites.
(2) If the server implemented password verification securely, then they should be using a slow function like PBKDF2, bcrypt, or scrypt to validate your passwords. These functions are designed to be slow so that if somebody gets access to the database, they will not be able to reverse many passwords: see Our password hashing has no clothes. Given that password checking is supposed to be slow, we don't want to be doing it often! Validation of access tokens is much quicker however.
(3) The system that grants you access to a resource ("resource provider") might not be the same as the system that checks your identity ("identity provider"). For example, many websites including StackOverflow allow you go login with your gmail account. In this case, Google is the identity provider and StackOverflow is the resource provider. Would you really want to provide your gmail password to StackOverflow? I hope not.
I have some problems to understand how to secure REST API.
When a client sign up, the password is hashed and sent to the server through HTTPS.
Then, the server store hash(password+privatesalt).
When the client consumes a rest service, he creates the request and a signature HMAC-SHA1 with his own password (like here).
Server side, how to sign the request to compare with the client signature if the password is hash-salted in the database ?
I know the data appears in clear over the web, but I just want to authenticate the user.
You are right. If the password is stored hashed & salted on the server side, it is not possible to verify the HMAC computed on the request: a MAC required a shared secret between the client and the server.
Some solutions could be:
using a dedicated API key which is not the user password. As far as I know, this is the AWS choice. The password is used for administrative operation on the user account (e.g. changing the billing contact) and the API key is only used by the API client. In this case if this API key is compromised, it is relatively easy to revoke it and generate a new one with a more limited impact on the security.
using HTTPS with X509 client certificates. This is a more heavyweight solution and probably more complex to setup. However it is transparent for the API users since the authentication is moved to the transport layer of the protocol.