Skip to content

Conversation

@aforward
Copy link
Collaborator

The goal of this lab is to look at how we can
authenticate API calls. As this is not a security course, we will
barely scratch the surface, but we will provide
many links for further reading.

Exercise 1: Configure PHPAPP

You will want to get up and running with the
sample phpapp available at

git clone git@github.com:professor-forward/phpapp.git

Follow the instructions in the
README.md

Exercise 2: Create a Client

Create a table to track clients and their tokens.

A client has (at least) a name, a token and some data

A few hints, you can create a default token using md5(random()::text),
and make data a jsonb field.

Exercise 3: Create an API

Create a new PHP file to track our api (public/api.php) with the following:

<?php
$reply = ["hello" => "world"];
header("Content-Type: application/json");
echo json_encode($reply);

Let's start our server.

php -S localhost:4000

And test our client. We will use Curl
as our client, but you can also use Postman.

curl -i http://localhost:4000/api.php

The output should look similar to

HTTP/1.1 200 OK
Host: localhost:4000
Date: Mon, 23 Mar 2020 00:50:02 GMT
Connection: close
X-Powered-By: PHP/7.3.9
Content-Type: application/json

{"hello":"world"}

Now change the API (api.php) to instead return all the headers
provided by the client. HINT: getallheaders

Let's add a custom header, and then we should it in our reply.

curl -i -H 'X-Men: Wolverine' http://localhost:4000/api.php

The output should include our header

HTTP/1.1 200 OK
Host: localhost:4000
Date: Mon, 23 Mar 2020 00:56:22 GMT
Connection: close
X-Powered-By: PHP/7.3.9
Content-Type: application/json

{"Host":"localhost:4000","User-Agent":"curl\/7.64.1","Accept":"*\/*","X-Men":"Wolverine"}

Using IMDB so some other source,
change the reply to be the actual that played the role in the X-Men.

For example,

curl -H 'X-Men: Wolverine' http://localhost:4000/api.php

Should now return

{"mutant":"Wolverine","name":"Logan"}

If you don't know the mutant, such as

curl -H 'X-Men: Wolfie' http://localhost:4000/api.php

Then return

{"mutant":"Wolfie","name":"Unknown"}

If you do not provide the expected header like below.

curl -i -H 'X-People: Wolfie' http://localhost:4000/api.php

Then return a 400 error code and message like. Hint: take
a look at http_response_code
and take a look at HTTP status codes.

HTTP/1.1 400 Bad Request
Host: localhost:4000
Date: Mon, 23 Mar 2020 01:24:41 GMT
Connection: close
X-Powered-By: PHP/7.3.9
Content-Type: application/json
{
    "error": "Please provide an X-Men mutant and reveal their human name.",
    "headers": {
        "Accept": "*/*",
        "Host": "localhost:4000",
        "User-Agent": "curl/7.64.1",
        "X-People": "Wolverine"
    }
}

Exercise 3: Authenticated API

We now have everything we need to create an authenticated API.

We will be using the Authentication header to store our secure
token. For more resources on securing your application, take a look at:

Let's update our our API to allow allow requests from professorcharlesxavier.

The example below should continue to work.

curl \
  -H 'Authentication: Bearer professorcharlesxavier' \
  -H 'X-Men: Wolverine' \
  http://localhost:4000/api.php

Should return our response as expected. Note that we are provided Bearer <token>. Hint: Look at explode
to split the string and list to capture them.

Anyone else should receive a
401 Reply. This example should fail

curl -i \
  -H 'Authentication: Bearer patrickstewart' \
  -H 'X-Men: Wolverine' \
  http://localhost:4000/api.php

Should return

HTTP/1.1 401 Unauthorized
Host: localhost:4000
Date: Mon, 23 Mar 2020 01:39:09 GMT
Connection: close
X-Powered-By: PHP/7.3.9
Content-Type: application/json

{"error":"Invalid token.","token":"patrickstewart","type":"Bearer"}

Exercise 3: Client Tokens

Instead of hard-coding the token to be professorcharlesxavier
let's use our clients table to authenticate this API.

Let us add two clients

name token
Big Co. d7d85f7eac7360d725b44d327445473e
Small Co. 9f8983a8494c8a003e064374ffb77cb6

And now only those two clients can access our API.

So the following call should work as expected

curl \
  -H 'Authentication: Bearer d7d85f7eac7360d725b44d327445473e' \
  -H 'X-Men: Wolverine' \
  http://localhost:4000/api.php

As the tokens are not hard-coded, we should also be able to make
a similar call.

curl \
  -H 'Authentication: Bearer 9f8983a8494c8a003e064374ffb77cb6' \
  -H 'X-Men: Wolverine' \
  http://localhost:4000/api.php

Any requests from others will be denied with a
401 Reply. This example should continue to fail

curl -i \
  -H 'Authentication: Bearer patrickstewart' \
  -H 'X-Men: Wolverine' \
  http://localhost:4000/api.php

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants