HTTP Basic Authentication vs Secret Key - php

After building a fairly simple API, I started looking into authentication where the basic HTTP authentication over SSL with just a username/password combination may appear weak for someone using it, although various discussions on here suggest it should be fine.
As this is the case, I looked into the API's from similar solutions which provide their users with a user ID and an API Key instead. The problem is I don't see how this is any stronger at all. I assume the Key is still saved just the same as a password, where from my perspective it just looks like they are calling a password a key.
Example:
https://github.com/Arie/serveme/blob/master/spec/fixtures/vcr/HiperzServer/_restart/visits_the_Hiperz_restart_URL.yml
How does the &api_key=hiperz_api_key&gs_id=3873 args offer any further security than just a username password? I would definitely like to implement something stronger than just user/pass over basic HTTP authentication and provide the end user with some type of token/key to use for access, but I am failing to see the additional strength from such approaches.

Well, there is always 2 step authentication which can be done(either by sending a message to their phone .. or maybe giving each user a randomly generated code to fill). Also, you can create your own encryption mechanism and add it to the functionality of your webpages. For example, you can encrypt the data using your own made up encryption key and then when it reaches where you want it you only know the key so you can de-crypt it.

Basic authentication is not recommended to protect APIs as I tried to explain in my answer here.
You are correct that using a client id and client secret is very similar to username and password authentication. The difference is that in the latter case you authenticate the user (a person), where in the former you authenticate the client (an application).
Whether you want to secure your API with a client id and secret depends on whether you can trust the client to keep them secret.
Either way, whether you have a trusted client, like a web application (living on a secured server) or an untrusted client like a JavaScript application or mobile application (living in the user's realm), token based authentication schemes (like OAuth2) provide a more secure way to protect your API than basic authentication. See my answer here for more information on the different ways to get tokens using OAuth 2.0

I am learning API's at the moment as well. My understanding is that by using an API key you can have more control over what permissions the user has. Also the API key can be reinvoked at any time as well. Also it will save the customer time from inputing log in details on each use of the API. I am not sure if that answered your question or not.

Related

How to secure a php based webservice

I'm developing one android application and I'm creating a php based webservice to retrieve the information from the database.
The thing is that I really don't know how to secure this service.
For example, if my android application needs to retrieve some information from the server it will call http://mywebservice.com/service.php, and it will send several POST parameters as the user and password to login, or something like, for example, one user id to retrieve his data.
Of course, anybody with the knowledge enough will be able to retrieve that data too. And this is what I don't want to happen.
Anybody who know the parameters to send to my server will be able to retrieve information from it.
How can I secure this?
I've been reading about OAuth, OAuth2, two legged and three legged implementations of it, https..
But at the moment, I really don't know how to secure this.
I want that the webservice only answer to my application and not to anybody else.
PS: Even there is something like http://myservice.com/get_information.php that you send an id and you can retrieve a lot of information. Of course, I control that in my application, only logged and authorized people can do that calling, but it's a problem anyway. What's the best way to do this kind of things?
Some concepts to secure a webservice(might be forgetting some notions):
Protocols: HTTPS in the current case so data are not transfered in a clear format.
The Sessions: A session has a lifetime, a unique identifier(session token/id/whatever) and contains an error code. When a user will call your webservice, a session will be created and its token answered back. At every call of the webservice you'll test if the session is still alive. You can add complexity to the expected inputs, outputs and exchanges. The error_code will be used for logging(errors can come from an attack or a bug of your webservice).
Data Encryption: Use asymetric functions like password_hash() or crypt() for authentication issues. Use symetric algorithms like AES 128(10 rounds) or 256 (14 rounds) for sensitive data you'll need to retrieve.
Testing inputs: If you find yourself inserting given arguments in a query, try to prevent SQL injection. Some bad-minded people can also try to send arguments which would make your webservice fail.
Go for standards: As Çagatay said, try to implement for example oAuth2 because standard is most of the time much better than what we'll build :S
Hope it helps.
edit: The REST security sheet is good also.
Always use SSL to prevent some man-in-the-middle attack. Otherwise someone that sniffs the connection (in case of connecting via public wi-fi or company networks it's a huge risk) can see the username and password.
Do not send username and password on each request, instead implement oAuth2, your client in this case will have to send the username and password only once and then for the other requests you'll have to send only the auth key. Good documentation for implementing a oauth server: http://www.sitepoint.com/creating-a-php-oauth-server/
Look at this document: https://www.owasp.org/index.php/REST_Security_Cheat_Sheet
I ended using OAuth. More especifically this library https://bshaffer.github.io/oauth2-server-php-docs/
If you follow the instructions it's really easy to use and it works very well. I think it's a really good way to start working with OAuth.

Implementing OAuth to REST API

I'm currently developing a RESTful API in PHP an I'd like to implement some user authentication to it. I have read through some literatures and the most efficient/secure way to allow authentication through rest api seems to be the use of the access tokens via the oauth protocol.
I have understood the way the protocol works but I don’t understand how to implement it to our api & database when the user has got his access token. The documentation about it is very unclear/nearly non-existent...
My idea was basically to save this access_token in my "users" MySQL table. That way we could verify if the user exists and has the appropriate permissions during each requests on the API.
However I’m not sure it is the most proper way to do that. Is it safe enough? How would you personally proceed to deal with that?
As this access token is like a temporary password, you can indeed store it in your table.
But as with storing passwords, you might want to hash and salt the token (depending on how relatively easy your tokens can be guessed). See the why's and how's here:
Secure hash and salt for PHP passwords

How do I authenticate users with a site API?

I want to build an API for users to build applications that easily interact with a site, and I was wondering what the best way to authenticate users would be.
Taking a look at other API's a lot of them have the user send the username and password as a GET parameter over a HTTPS connection. Is this the best way to go about it? Or are there other methods that I should look into or consider?
I've seen OAuth been tossed around and it looks like a good solution, but just for a simple API is it overkill?
You can use API key's. Generate a unique hash tied to an account upon request. Then check that the key is a valid key. As long as the API doesn't have any major security issues with someone using someone else's key then Authorization isn't needed. If there is a problem with someone using someone else's key then Authentication would be justified.
This is usually achieved with cookies.
The client sends their username and password with a POST request to your API (do not use GET, that's insecure). If the credentials are acceptable, then generate a random, unique session key, store it on your side and send it in a cookie back to the client (see setcookie()).
When the client now makes further requests, they send the session key cookie with the request. Check $_COOKIE for the session key if it matches a stored key on your side; if yes, that means the user authenticated.
Take note that this minimal example is vulnerable to brute-force attacks trying to guess valid session keys. You need to log invalid keys that clients send in their cookies and block their IP address for some period of time to prevent this.
Username / password in a GET isn't a great way to do this because you're potentially exposing the whole user account for hijacking even if the API has more limited functionality than logging into the site. So it's good practice to separate concerns between Web-site login and API access.
I'm not sure which case you're in but:
If the users are business customers of somekind who are embedding some type of widget or code in another website then it's probably best to use an API key which is scoped to the referrer domain (much like Google Maps does).
If they are end-users who won't know anything about the API but are going to be using Apps built by third parties then oAuth is likely to be your best bet, otherwise your users might literally be giving their usernames/passwords to unknown third parties. It's more complex but likely to be worth it in the long run.
To get a bunch of this stuff out of the box you can use something like 3scale (http://www.3scale.net) and it'll handle most of it for you (disclaimer, I work there so adjust for bias!) or there are open source libraries for oAuth in most languages (in PHP Zend-OAuth component might do the job for you).

simple authorisation in web api

I want to make nice and clean api; I'm making site and I want to offer the ability to mobile apps use web API of my site.
I don't want to use oAuth, becouse the mobile and embedded applications that are facing the biggest hurdle, as they may not be able to bring up and/or control the web browser. Also its a little complicate.
I know, that HTTP basic authorisation is not safe, but it's so simple... I want to use it in my api.
I have somee users logins and their passwords (md5-encoded) in mysql base, but how to use those data in this HTTP basic authorisation?
Generate a random unique string for each user in your database and make that string available to the end users. When they access the api ask them to enter that unique string that you supplied--this is their 'key'. Each time a users app accesses the api they pass the key which links directly to a unique account and that is how you authorize them. It is essentially user name and password all in one.
While the above example is generic you should also take things like security into account--for example, when possible, pass the device ID from the mobile along and use that during authentication, or use their current password hash during their API key generation so if they change their password the key will stop working and they have to get a new one--this way they can control access if their key is lost.
It doesn't have to be complicated, it just has to be safe. =)
The PHP manual has an example
Jus google your question "PHP HTTP basic" and here you are
http://php.net/manual/en/features.http-auth.php
it is as simple as sending a few HTTP headers.
Also note that digest authorization considered to be more safe but less compatible with clients.

Web API Security

I'm asked to write a Web API for an application (pc executable, not web-app) that will allow sending emails.
A user clicks something, the app communicates with the API which generates an email and sends it out.
I have to make sure noone unauthorised will have access to the API, so I need to make some kind of authentication and I haven't got an idea how to do it correctly.
There will be more applications accessing the API.
First thought was - send username and password, but this doesn't solve the problem really. Because if someone decompiles the application, they'll have the request url and variables including user/password or simply it can just be sniffed.
so... what options do I have?
I'm fairly sure secure connection (SSL) is not available to me at the moment, but still, this won't help me against the decompiling problem, will it?
EDIT
I haven't said that initially, but the user will not be asked for the username/password. It's the application(s) that will have to be authenticated, not users of the application(s).
The distribution of your software is really the crux of the problem. Hashing user names and passwords and storing them in the software isn't any more useful than storing un-hashed values, as either one would work to access the API server. If you're going to implement usernames and passwords for your users, I think you can use that as a pre-cursor to API control without storing the values in the software itself. Let me describe this in two parts.
Request Signatures
The most common method in use for API request verification is request signatures. Basically, before a request is sent to an API server, the parameters in the request are sorted, and a unique key is added to the mix. The whole lot is then used to produce a hash, which is appended to the request. For example:
public static function generateRequestString(array $params, $secretKey)
{
$params['signature'] = self::generateSignature($params, $secretKey);
return http_build_query($params,'','&');
}
public static function generateSignature($secretKey, array $params)
{
$reqString = $secretKey;
ksort($params);
foreach($params as $k => $v)
{
$reqString .= $k . $v;
}
return md5($reqString);
}
You could create an API request query string using the above code simply by calling the generateRequestString() method with an array of all the parameters you wanted to send. The secret key is something that is provided uniquely to each user of the API. Generally you pass in your user id to the API server along with the signature, and the API server uses your id to fetch your secret key from the local database and verify the request in the same way that you built it. Assuming that the key and user id are correct, that user should be the only one able to generate the correct signature. Note that the key is never passed in the API request.
Unfortunately, this requires every user to have a unique key, which is a problem for your desktop app. Which leads me to step two.
Temporal Keys
So you can't distribute keys with the application because it can be decompiled, and the keys would get out. To counter-act that, you could make very short-lived keys.
Assuming that you've implemented a part of the desktop app that asks users for their username and password, you can have the application perform an authentication request to your server. On a successful authentication, you could return a temporal key with the response, which the desktop app could then store for the lifetime of the authorized session, and use for API requests. Because you mentioned that you can't use SSL, this initial authentication is the most vulnerable part, and you have to live with some limitations.
The article Andy E suggested is a good approach (I voted it up). It's basically a handshake to establish a short-lived key that can be used to authenticate. The same key could be used for signature hashing. You could also take your chances and just send the username/password unencrypted and get a temporal key (it would only happen once), but you'd have to be aware that it could be sniffed.
Summary
If you can establish a temporal session key, you won't have to store anything in the client program that can be decompiled. A username/password sent once to your server should be enough to establish that. Once you have that key, you can use it to create requests in the desktop apps, and verify requests on the API server.
I would recommend you check out OAuth. it should definitely help you out in sorting out the security issues with authorizing tools to access your API.
http://oauth.net
Someone is always going to be able to decompile and hunt for the variables. An obfuscator might be able to hide them a little better. Sniffing is also easy without SSL unless you use a private and public keyset to encrypt the request data client side and decrypt server side (but obviously this key will be stored in the client application).
The best thing to do is provide as many layers of protection as you think you will need, creating a secure connection and obfuscating your code. You could look at the following article, which demonstrates a secure connection without using SSL:
http://www.codeproject.com/KB/security/SecureStream.aspx
As mattjames mentioned, you should never store passwords in plain text format. When the user enters their password into the application, store a hash of the password. The same hash should be stored on the server. That way, if the hash is seen by an interceptor they at least wouldn't see the user's original password.
You will need to use SSL if you need to prevent people from seeing the plain text password that is sent from the app over the network to the API.
For the decompilation issue, you would want to store the hash of the password in the API, not the original password. See explanation here: http://phpsec.org/articles/2005/password-hashing.html.

Categories