API authentication

I want to create an api, but how to implement a good authentication?
I am thinking to accept a list of allowed IPs with a secret_key as header like below:

if (!in_array($_SERVER['REMOTE_ADDR'], $ip_array) || $_SERVER['HTTP_SECRET_KEY'] != "API_KEY_GOES_HERE") {
    $output = array (
                     "error" => true,
                     "message" => "Authentication failed!");
    echo json_encode($output);
    die();
}

Is it enough as a good/secure authentication? or how you’d create an api authentication?

that requires that the client users have a fixed IP, which is not always given.

the APIs I know use either the API key directly (as part of the URL or message) along with SSL or the submitted data are hashed with the API key as salt and added this hash to the data.

that ip is the server ip where their api script is located in fact this is $_SERVER['SERVER_ADDR'] of where api script is located, when it sends data to target RESTApi server via curl, target server gets it as $_SERVER['REMOTE_ADDR'], this is not end-user ip but client server ip, so this is fixed. This way, target server allows client server to send/receive data from/to it.
As about hashing data, if it is posting data yes good idea but what about get method? it is just sending get method to receive some data so no data is posted that it generates a hash of those data, in this case what to do or what to hash?

you can put it in an URL parameter.

if the client (UA) does send this field. an UA may choose to (not) send any header information it likes. if you want to rely on a certain piece of information, make it part of the API.

As about first part: we were talking about authentication methods and hashing posted data that server can verify them to make sure if posted data is not tampered, right? (or you meant something else that I did not understand?) then I said if it is posting data it can generate a hash of them for authentication/verification but if it is not actually posting any data and is just contacting with get method to query/fetch some data, then what should it hash for authentication? please clarify.

As about second: you meant some severs may ban headers to be sent? so this is better that ip would not be part of header but sent as a normal data? Did I get you correctly?

if you request data via GET, you still need some kind of key to identify the kind of data you’re interested in, then you have data to hash. Whether the data reside in GET or POST does not matter for that.

alternately, if you “encode” the data as part of the URL path, you can hash “no data”, i.e. an empty string.

there is no rule that forces a UA to send anything but the request uri header (that is, something along GET <uri> HTTP/1.1)

In the code I gave above it validates the api key with if statement, but instead if I want to use HTTP Basic Authentication, what should I do? for example if I send “username:password” in header like x-api-key how should I get that for Basic Authentication instead of if statement I gave above?

well, I searched and found this: http://docstore.mik.ua/orelly/webprog/pcook/ch08_10.htm
it tries to validate credentials and sends HTTP Basic Authentication header if not authenticated, the difference with my code was that it just outputs a json and die the script, what’s the major difference if I change my json output/die of my code to http basic header? I don’t understand the benefit?

I think the only benefit is that it just prompts for username/password for direct access to script, but if my script is design to be accessed remotely for RESTApi, then there should not be a benefit for http basic vs json/die? am I right? please clarify.

that’s two different matters. the one is about HTTP communication, the other about the running script.

you can even authenticate via HTTP Auth without the use of PHP.

So as I said the only benefit of Basic Auth is that it just prompts for username/password for direct access to script, but if my script is designed to be accessed remotely for RESTApi, then there should not be a benefit for http basic vs json/die? am I right?

no.

HTTP Auth triggers a prompt in browser that’s true, but if you’re not using a browser, you have to supply the appropriate header fields yourself. see RFC 2617 for details.

  1. See https://github.com/wgm/cerb/blob/stable/features/cerberusweb.restapi/api/App.php#L345
    and http://cerberusweb.com/book/latest/developer_guide/rest_api/examples/php.html

it sends timestamp to restapi server and it checks whether the timestamp is within past and future 10 minutes, I could not understand the timezone problem, if client and server have 10 hours timezone difference, this RFC2822 still creates the same timestamp regardless timezone that it validates it?

  1. As about my main question about api authentication, is it good idea to use 10 minutes timestamp difference
    for authentication? what is the difference and what is the advantage of this way?

any advice yet about timestamp on two servers with 10 hours timezone difference, as I asked above?

I’d use a UNIX Timestamp, if the time range works for you.

1 Like

unixtimestamp on two servers with 10 hours timezone difference, will not be the same. if client timezone is -5 and it generates a timestamp and sends it to target server with timzone +5, and this target server wants to validate if this timestamp is between past and future 10 minutes, will it be validated?

a unix timestamp is completely independent of timezones …

Aha, got it! so on targert server it will be validated…

  1. As about my main question about api authentication, is it good idea to use 10 minutes timestamp difference
    for authentication as I gave the links in previous post?
  2. Does it happen a request will be accidentally sent twice after several minutes (e.g. 10 minutes)?
  1. I don’t see the need for that. if you need to be authenticated for a public API, require the credentials for every API action.

  2. on the internet anything can happen. If your API action is resource-intensive, consider caching the result.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.