For learning purposes, I have created a simple PHP application which implements a web service with a basic authentication mechanism. I know that basic authentication is not the best mechanism, but I just want to start with this mechanism before I start with OAuth2.0 or something else.
So my current environment looks like this:
Multiple clients provide data in JSON representation only over an https connection.
- Client 1: https://example1.com/api/data/
- Client 2: https://example2.com/api/data/
- ...
These resources are protected through a basic authentication header and the clients provide data only if the credentials are valid:
public function provideData()
{
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="Example BasicAuth"');
header('HTTP/1.0 401 Unauthorized');
die('Authentication failed');
}
$user = $_SERVER['PHP_AUTH_USER'];
$password = $_SERVER['PHP_AUTH_PW'];
// not relevant database stuff ...
$password = hash('sha512', $password . $saltDb);
if (!hash_equals($password, $passwordDb)) {
die('Authentication failed');
}
// not relevant data handling stuff ...
return json_encode($data);
}
So every client stores his own credentials into a client database and provides data only if the entered data is valid. (I don't want to store credentials as plain text into the client database so I store salted hashed passwords.). This is working great for me, but now comes the part where I got into trouble:
There is a server which should collect the data of all these clients. For this reason, I can create multiple client objects on the server side which contains data like the resource URL, username, password and so on, but I don't want to store the client passwords as plain text into the server database, but I can't store hashed client passwords on server side too, because the server will don't know about the real password then.
So I think the only solution is to implement a custom encrypt and decrypt function to store an encrypted client password into the server database. Then only the server knows about encryption and decryption and could handle this or is there a better way to store the required client credentials on the server side?
EDIT
I will try to clarify "the server will don't know about the real password". Please interrupt me if I am wrong, but a basic HTTP authentication will use plain client data (username and password) and sends a base64 encoded string of them, e.g. "Authorization: Basic dXNlcjpwYXNzd29yZA==" to get access to the resource. For this reason, the server has to use the password as plaintext to build a request with a basic authentication header.
The problem is when I create a client object on the server side, then I have to store the credentials into the server database and I could hash the password there, but hash functions are one-way functions so the server will not be able to get the plain password from the hashed password back, without storing the plain password too, but if the server needs the plain password to get access to the resource then I can't use a hash function to "protect" the password into the database.